// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. /** * Generic utility functions. Stuff that should possibly be in core. */ #library('utils'); #import('dart:crypto'); #import('dart:isolate'); /** A pair of values. */ class Pair { E first; F last; Pair(this.first, this.last); String toString() => '($first, $last)'; bool operator==(other) { if (other is! Pair) return false; return other.first == first && other.last == last; } } // TODO(rnystrom): Move into String? /** Pads [source] to [length] by adding spaces at the end. */ String padRight(String source, int length) { final result = new StringBuffer(); result.add(source); while (result.length < length) { result.add(' '); } return result.toString(); } /** * Runs [fn] after [future] completes, whether it completes successfully or not. * Essentially an asynchronous `finally` block. */ always(Future future, fn()) { var completer = new Completer(); future.then((_) => fn()); future.handleException((_) { fn(); return false; }); } /** * Flattens nested lists into a single list containing only non-list elements. */ List flatten(List nested) { var result = []; helper(list) { for (var element in list) { if (element is List) { helper(element); } else { result.add(element); } } } helper(nested); return result; } /** * Asserts that [iter] contains only one element, and returns it. */ only(Iterable iter) { var iterator = iter.iterator(); assert(iterator.hasNext()); var obj = iterator.next(); assert(!iterator.hasNext()); return obj; } /** * Replace each instance of [matcher] in [source] with the return value of [fn]. */ String replace(String source, Pattern matcher, String fn(Match)) { var buffer = new StringBuffer(); var start = 0; for (var match in matcher.allMatches(source)) { buffer.add(source.substring(start, match.start())); start = match.end(); buffer.add(fn(match)); } buffer.add(source.substring(start)); return buffer.toString(); } /** * Returns whether or not [str] ends with [matcher]. */ bool endsWithPattern(String str, Pattern matcher) { for (var match in matcher.allMatches(str)) { if (match.end() == str.length) return true; } return false; } /** * Returns the hex-encoded sha1 hash of [source]. */ String sha1(String source) => CryptoUtils.bytesToHex(new SHA1().update(source.charCodes()).digest()); /** * Returns a [Future] that completes in [milliSeconds]. */ Future sleep(int milliSeconds) { var completer = new Completer(); new Timer(milliSeconds, completer.complete); return completer.future; }