From 65ce3e002dd52eb6d38fdfb0c8d49ffbcf40a229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BB=D0=B0=D0=B2=D0=B0=20=D0=A3=D0=BA=D1=80=D0=B0?= =?UTF-8?q?=D1=97=D0=BD=D1=96!=20=D0=93=D0=B5=D1=80=D0=BE=D1=8F=D0=BC=20?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=D0=B0!?= <777696+ncave@users.noreply.github.com> Date: Sun, 22 Sep 2024 00:50:37 +0000 Subject: [PATCH] [Rust] Added missing ResizeArray methods and tests (#3896) --- src/Fable.Cli/CHANGELOG.md | 8 +- src/Fable.Transforms/Rust/Replacements.fs | 134 +++---- src/fable-library-rust/src/Array.fs | 35 -- src/fable-library-rust/src/Interop.rs | 12 +- src/fable-library-rust/src/Native.rs | 11 +- src/fable-library-rust/src/NativeArray.rs | 312 ++++++++++++++- tests/Rust/tests/src/ResizeArrayTests.fs | 448 +++++++++++++--------- 7 files changed, 634 insertions(+), 326 deletions(-) diff --git a/src/Fable.Cli/CHANGELOG.md b/src/Fable.Cli/CHANGELOG.md index a3ab53261a..6aeec23df1 100644 --- a/src/Fable.Cli/CHANGELOG.md +++ b/src/Fable.Cli/CHANGELOG.md @@ -7,14 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +* [Rust] Added support for Dictionary/HashSet comparers (by @ncave) +* [Rust] Updated support for interface object expressions (by @ncave) +* [Rust] Added missing ResizeArray methods and tests (by @ncave) + ## 4.21.0 - 2024-09-19 ### Added * [JS/TS] Add support for `OrdinalIgnoreCase` overload for `String.EndsWith` (#3892) (by @goswinr) * [JS/TS] Add `uri.Port`, `uri.IsDefaultPort` (by @MangelMaxime) -* [Rust] Added support for Dictionary/HashSet comparers (by @ncave) -* [Rust] Updated support for interface object expressions (by @ncave) ### Changed diff --git a/src/Fable.Transforms/Rust/Replacements.fs b/src/Fable.Transforms/Rust/Replacements.fs index 7067904f6e..c6788df941 100644 --- a/src/Fable.Transforms/Rust/Replacements.fs +++ b/src/Fable.Transforms/Rust/Replacements.fs @@ -147,6 +147,15 @@ let makeRefFromMutableFunc com ctx r t (value: Expr) = value let toNativeIndex expr = TypeCast(expr, UNativeInt.Number) +let toLowerFirstWithArgsCountSuffix (args: Expr list) meth = + let argCount = List.length args + let meth = Naming.lowerFirst meth + + if argCount > 1 then + meth + (string argCount) + else + meth + let toChar com (arg: Expr) = match arg.Type with | Char -> arg @@ -338,7 +347,6 @@ let emitFormat (com: ICompiler) r t (args: Expr list) macro = let unboxedArgs = args |> FSharp2Fable.Util.unboxBoxedArgs Helper.LibCall(com, "String", macro, t, unboxedArgs) - let getMut expr = Helper.InstanceCall(expr, "get_mut", expr.Type, []) @@ -1601,79 +1609,39 @@ let seqModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg let resizeArrays (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) = match i.CompiledName, thisArg, args with - | ".ctor", _, [] -> - // makeArray (getElementType t) [] |> Some - Helper.LibCall(com, "NativeArray", "new_empty", t, [], ?loc = r) |> Some - | ".ctor", _, [ ExprTypeAs(Number(Int32, _), idx) ] -> - Helper.LibCall(com, "NativeArray", "new_with_capacity", t, [ idx ], ?loc = r) - |> Some - // Optimize expressions like `ResizeArray [|1|]` or `ResizeArray [1]` - | ".ctor", _, [ ArrayOrListLiteral(vals, typ) ] -> makeArray typ vals |> Some + | ".ctor", _, [] -> Helper.LibCall(com, "NativeArray", "new_empty", t, args, ?loc = r) |> Some + | ".ctor", _, [ ExprType(Number(Int32, _)) ] -> + Helper.LibCall(com, "NativeArray", "new_with_capacity", t, args, ?loc = r) + |> Some + | ".ctor", _, [ ExprType(IEnumerable) ] -> + Helper.LibCall(com, "NativeArray", "new_from_enumerable", t, args, ?loc = r) + |> Some | ".ctor", _, [ arg ] -> toArray com t arg |> Some + | "get_Capacity", Some ar, _ -> Helper.LibCall(com, "NativeArray", "get_Capacity", t, [ ar ], ?loc = r) |> Some + | "get_Count", Some ar, _ -> Helper.LibCall(com, "NativeArray", "get_Count", t, [ ar ], ?loc = r) |> Some | "get_Item", Some ar, [ idx ] -> getExpr r t ar idx |> Some | "set_Item", Some ar, [ idx; value ] -> setExpr r ar idx value |> Some - | "Add", Some(MaybeCasted(ar)), [ arg ] -> - Helper.LibCall(com, "NativeArray", "add", t, [ ar; arg ], ?loc = r) |> Some - | "Remove", Some(MaybeCasted(ar)), [ arg ] -> - Helper.LibCall(com, "Array", "removeInPlace", t, [ arg; ar ], ?loc = r) |> Some - | "RemoveAll", Some ar, [ arg ] -> - Helper.LibCall(com, "Array", "removeAllInPlace", t, [ arg; ar ], ?loc = r) - |> Some - | "FindIndex", Some ar, [ arg ] -> - Helper.LibCall(com, "NativeArray", "FindIndex", t, [ ar; arg ], ?loc = r) - |> Some - | "FindLastIndex", Some ar, [ arg ] -> - Helper.LibCall(com, "Array", "findLastIndex", t, [ arg; ar ], ?loc = r) |> Some - | "ForEach", Some ar, [ arg ] -> makeInstanceCall r t i ar "forEach" [ arg ] |> Some | "GetEnumerator", Some(MaybeCasted(ar)), _ -> Helper.LibCall(com, "Seq", "Enumerable::ofArray", t, [ ar ], ?loc = r) |> Some - | "get_Count", Some(MaybeCasted(ar)), _ -> Helper.LibCall(com, "NativeArray", "count", t, [ ar ], ?loc = r) |> Some - | "Clear", Some(MaybeCasted(ar)), [] -> makeInstanceCall r t i (getMut ar) "clear" [] |> Some - | "ConvertAll", Some ar, [ arg ] -> Helper.LibCall(com, "Array", "map", t, [ arg; ar ], ?loc = r) |> Some - | "Find", Some ar, [ arg ] -> - let opt = Helper.LibCall(com, "Array", "tryFind", t, [ arg; ar ], ?loc = r) - - Helper.LibCall(com, "Option", "defaultArg", t, [ opt; getZero com ctx t ], ?loc = r) - |> Some - | "Exists", Some ar, [ arg ] -> - Helper.LibCall(com, "Array", "exists", t, [ arg; ar ], i.SignatureArgTypes, ?loc = r) - |> Some - | "FindLast", Some ar, [ arg ] -> - let opt = Helper.LibCall(com, "Array", "tryFindBack", t, [ arg; ar ], ?loc = r) - - Helper.LibCall(com, "Option", "defaultArg", t, [ opt; getZero com ctx t ], ?loc = r) - |> Some - | "FindAll", Some ar, [ arg ] -> Helper.LibCall(com, "Array", "filter", t, [ arg; ar ], ?loc = r) |> Some - | "AddRange", Some ar, [ arg ] -> - Helper.LibCall(com, "Array", "addRangeInPlace", t, [ arg; ar ], ?loc = r) - |> Some - | "GetRange", Some ar, [ idx; cnt ] -> - Helper.LibCall(com, "Array", "getSubArray", t, [ ar; idx; cnt ], ?loc = r) - |> Some - | "Contains", Some(MaybeCasted(ar)), [ arg ] -> - Helper.LibCall(com, "Array", "contains", t, [ arg; ar ], i.SignatureArgTypes, ?loc = r) - |> Some - | "IndexOf", Some ar, [ arg ] -> - Helper.LibCall(com, "Array", "indexOf", t, [ ar; arg ], i.SignatureArgTypes, ?loc = r) - |> Some - | "Insert", Some ar, [ idx; arg ] -> makeInstanceCall r t i (getMut ar) "insert" [ toNativeIndex idx; arg ] |> Some - | "InsertRange", Some ar, [ idx; arg ] -> - Helper.LibCall(com, "Array", "insertRangeInPlace", t, [ idx; arg; ar ], ?loc = r) - |> Some - | "RemoveRange", Some ar, args -> makeInstanceCall r t i ar "splice" args |> Some - | "RemoveAt", Some ar, [ idx ] -> makeInstanceCall r t i (getMut ar) "remove" [ toNativeIndex idx ] |> Some - | "Reverse", Some ar, [] -> makeInstanceCall r t i (getMut ar) "reverse" args |> Some - | "Sort", Some ar, [] -> - // can't use .sort() as it needs T: Ord - Helper.LibCall(com, "Array", "sortInPlace", t, [ ar ], i.SignatureArgTypes, ?loc = r) + | ("Add" | "AddRange" | "Clear" | "Contains" | "ConvertAll" | "Exists" | "GetRange" | "Slice" | "ForEach" | "FindAll" | "Find" | "FindLast" | "FindIndex" | "FindLastIndex" | "Insert" | "InsertRange" | "Remove" | "RemoveAt" | "RemoveAll" | "RemoveRange" | "ToArray" | "TrimExcess" | "TrueForAll") as meth, + Some ar, + args -> + // methods without overrides + let meth = Naming.lowerFirst meth + Helper.LibCall(com, "NativeArray", meth, t, (ar :: args), ?loc = r) |> Some + | ("BinarySearch" | "CopyTo" | "IndexOf" | "LastIndexOf" | "Reverse") as meth, Some ar, args -> + // methods with some overrides + let meth = meth |> toLowerFirstWithArgsCountSuffix args + Helper.LibCall(com, "NativeArray", meth, t, (ar :: args), ?loc = r) |> Some + | "Sort", Some ar, [] -> Helper.LibCall(com, "NativeArray", "sort", t, (ar :: args), ?loc = r) |> Some + | "Sort", Some ar, [ ExprType(DelegateType _) ] -> + Helper.LibCall(com, "NativeArray", "sortBy", t, (ar :: args), ?loc = r) |> Some + | "Sort", Some ar, [ comparer ] -> + Helper.LibCall(com, "NativeArray", "sortWith", t, (ar :: args), ?loc = r) + |> Some + | "Sort", Some ar, [ index; count; comparer ] -> + Helper.LibCall(com, "NativeArray", "sortWith2", t, (ar :: args), ?loc = r) |> Some - | "Sort", Some ar, [ ExprType(DelegateType _) as comparer ] -> - let cmp = Helper.LibCall(com, "Native", "makeCompare", t, [ comparer ], ?loc = r) - - makeInstanceCall r t i (getMut ar) "sort_by" [ cmp ] |> Some - // | "Sort", Some ar, [arg] -> - // Helper.LibCall(com, "Array", "sortInPlaceWithComparer", t, [ar; arg], i.SignatureArgTypes, ?loc=r) |> Some - | "ToArray", Some ar, [] -> Helper.LibCall(com, "NativeArray", "new_copy", t, [ ar ], ?loc = r) |> Some | _ -> None let collectionExtensions @@ -1743,30 +1711,22 @@ let copyToArray (com: ICompiler) r t (i: CallInfo) args = let arrays (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) = match i.CompiledName, thisArg, args with - | "get_Length", Some ar, _ -> Helper.LibCall(com, "NativeArray", "count", t, [ ar ], ?loc = r) |> Some + | "get_Length", Some ar, _ -> Helper.LibCall(com, "NativeArray", "get_Count", t, [ ar ], ?loc = r) |> Some | "get_Item", Some ar, [ idx ] -> getExpr r t ar idx |> Some | "set_Item", Some ar, [ idx; value ] -> setExpr r ar idx value |> Some - | "Clone", Some ar, _ -> Helper.LibCall(com, "NativeArray", "new_copy", t, [ ar ], ?loc = r) |> Some + | "Clone", Some ar, _ -> Helper.LibCall(com, "NativeArray", "toArray", t, [ ar ], ?loc = r) |> Some | "Copy", None, [ _source; _sourceIndex; _target; _targetIndex; _count ] -> copyToArray com r t i args | "Copy", None, [ source; target; count ] -> copyToArray com r t i [ source; makeIntConst 0; target; makeIntConst 0; count ] | "ConvertAll", None, [ source; mapping ] -> - Helper.LibCall(com, "Array", "map", t, [ mapping; source ], ?loc = r) |> Some - | "IndexOf", None, [ ar; arg ] -> - Helper.LibCall(com, "Array", "indexOf", t, args, i.SignatureArgTypes, ?loc = r) - |> Some + Helper.LibCall(com, "NativeArray", "convertAll", t, args, ?loc = r) |> Some + | "IndexOf", None, [ ar; arg ] -> Helper.LibCall(com, "NativeArray", "indexOf", t, args, ?loc = r) |> Some | "GetEnumerator", Some ar, _ -> Helper.LibCall(com, "Seq", "Enumerable::ofArray", t, [ ar ], ?loc = r) |> Some - | "Reverse", None, [ ar ] -> makeInstanceCall r t i (getMut ar) "reverse" [] |> Some - | "Sort", None, [ ar ] -> - // can't use .sort() as it needs T: Ord - Helper.LibCall(com, "Array", "sortInPlace", t, [ ar ], i.SignatureArgTypes, ?loc = r) - |> Some + | "Reverse", None, [ ar ] -> Helper.LibCall(com, "NativeArray", "reverse", t, args, ?loc = r) |> Some + | "Sort", None, [ ar ] -> Helper.LibCall(com, "NativeArray", "sort", t, args, ?loc = r) |> Some | "Sort", None, [ ar; ExprType(DelegateType _) as comparer ] -> - let cmp = Helper.LibCall(com, "Native", "makeCompare", t, [ comparer ], ?loc = r) - - makeInstanceCall r t i (getMut ar) "sort_by" [ cmp ] |> Some - // | "Sort", None, [ar; arg] -> - // Helper.LibCall(com, "Array", "sortInPlaceWithComparer", t, [ar; arg], i.SignatureArgTypes, ?loc=r) |> Some + Helper.LibCall(com, "NativeArray", "sortBy", t, args, ?loc = r) |> Some + | "Sort", None, [ ar; comparer ] -> Helper.LibCall(com, "NativeArray", "sortWith", t, args, ?loc = r) |> Some | _ -> None let arrayModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Expr option) (args: Expr list) = @@ -1783,7 +1743,7 @@ let arrayModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Ex | "ToList", args -> Helper.LibCall(com, "List", "ofArray", t, args, i.SignatureArgTypes, ?loc = r) |> Some - | ("Length" | "Count"), [ ar ] -> Helper.LibCall(com, "NativeArray", "count", t, [ ar ], ?loc = r) |> Some + | ("Length" | "Count"), [ ar ] -> Helper.LibCall(com, "NativeArray", "get_Count", t, [ ar ], ?loc = r) |> Some | "Item", [ idx; ar ] -> getExpr r t ar idx |> Some | "Get", [ ar; idx ] -> getExpr r t ar idx |> Some | "Set", [ ar; idx; value ] -> setExpr r ar idx value |> Some @@ -1792,9 +1752,7 @@ let arrayModule (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (_: Ex | "Empty", [] -> createArray com ctx r t i (makeIntConst 0) None |> Some | "Singleton", [ value ] -> createArray com ctx r t i (makeIntConst 1) (Some value) |> Some | "IsEmpty", [ ar ] -> makeInstanceCall r t i ar "is_empty" [] |> Some - | "Copy", [ ar ] -> - Helper.LibCall(com, "NativeArray", "new_copy", t, args, i.SignatureArgTypes, ?loc = r) - |> Some + | "Copy", [ ar ] -> Helper.LibCall(com, "NativeArray", "toArray", t, args, ?loc = r) |> Some | "CopyTo", args -> copyToArray com r t i args | ("Concat" | "Transpose" as meth), [ arg ] -> Helper.LibCall(com, "Array", Naming.lowerFirst meth, t, [ toArray com t arg ], i.SignatureArgTypes, ?loc = r) diff --git a/src/fable-library-rust/src/Array.fs b/src/fable-library-rust/src/Array.fs index 4023a03896..47faa53f40 100644 --- a/src/fable-library-rust/src/Array.fs +++ b/src/fable-library-rust/src/Array.fs @@ -467,41 +467,6 @@ let truncate (count: int) (source: 'T[]) : 'T[] = getSubArray source 0 count -// let addInPlace (x: 'T) (source: 'T[]) = -// // if isTypedArrayImpl source then invalidArg "array" "Typed arrays not supported" -// pushImpl source x |> ignore - -// let addRangeInPlace (range: seq<'T>) (source: 'T[]) = -// // if isTypedArrayImpl source then invalidArg "array" "Typed arrays not supported" -// for x in range do -// addInPlace x source - -// let insertRangeInPlace index (range: seq<'T>) (source: 'T[]) = -// // if isTypedArrayImpl source then invalidArg "array" "Typed arrays not supported" -// let mutable i = index -// for x in range do -// insertImpl source i x |> ignore -// i <- i + 1 - -// let removeInPlace (item: 'T) (source: 'T[]) = -// // if isTypedArrayImpl source then invalidArg "array" "Typed arrays not supported" -// let i = indexOfImpl source item 0 -// if i > -1 then -// spliceImpl source i 1 |> ignore -// true -// else -// false - -// let removeAllInPlace predicate (source: 'T[]) = -// let rec countRemoveAll count = -// let i = findIndexImpl predicate source -// if i > -1 then -// spliceImpl source i 1 |> ignore -// countRemoveAll count + 1 -// else -// count -// countRemoveAll 0 - // TODO: Check array lengths let copyTo (source: 'T[]) sourceIndex (target: 'T[]) targetIndex count = let diff = targetIndex - sourceIndex diff --git a/src/fable-library-rust/src/Interop.rs b/src/fable-library-rust/src/Interop.rs index 541cef43d3..c1c5bf4699 100644 --- a/src/fable-library-rust/src/Interop.rs +++ b/src/fable-library-rust/src/Interop.rs @@ -63,7 +63,7 @@ pub mod ListExt { } pub mod SetExt { - use crate::Native_::{makeCompare, seq_to_iter, Func2, Vec}; + use crate::Native_::{make_compare, seq_to_iter, Func2, Vec}; use crate::Set_::{add, compareTo, empty, equals, toSeq, Set}; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; @@ -98,13 +98,13 @@ pub mod SetExt { impl PartialOrd for Set { fn partial_cmp(&self, other: &Self) -> Option { - Some(makeCompare(Func2::from(compareTo))(self, other)) + Some(make_compare(Func2::from(compareTo))(self, other)) } } impl Ord for Set { fn cmp(&self, other: &Self) -> Ordering { - makeCompare(Func2::from(compareTo))(self, other) + make_compare(Func2::from(compareTo))(self, other) } } @@ -147,7 +147,7 @@ pub mod SetExt { pub mod MapExt { use crate::Map_::{add, compareTo, empty, equals, iterate, toSeq, Map}; - use crate::Native_::{makeCompare, seq_to_iter, Func2, Vec}; + use crate::Native_::{make_compare, seq_to_iter, Func2, Vec}; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; @@ -181,13 +181,13 @@ pub mod MapExt { impl PartialOrd for Map { fn partial_cmp(&self, other: &Self) -> Option { - Some(makeCompare(Func2::from(compareTo))(self, other)) + Some(make_compare(Func2::from(compareTo))(self, other)) } } impl Ord for Map { fn cmp(&self, other: &Self) -> Ordering { - makeCompare(Func2::from(compareTo))(self, other) + make_compare(Func2::from(compareTo))(self, other) } } diff --git a/src/fable-library-rust/src/Native.rs b/src/fable-library-rust/src/Native.rs index 472fdf20eb..292fb2aed1 100644 --- a/src/fable-library-rust/src/Native.rs +++ b/src/fable-library-rust/src/Native.rs @@ -130,7 +130,16 @@ pub mod Native_ { } } - pub fn makeCompare( + pub fn partial_compare(x: &T, y: &T) -> Ordering { + match x.partial_cmp(y) { + Some(ordering) => ordering, + None if y == y => Ordering::Less, // y is not NaN + None if x == x => Ordering::Greater, // x is not NaN + None => Ordering::Equal, + } + } + + pub fn make_compare( comparer: Func2, ) -> impl Fn(&T, &T) -> Ordering { move |x, y| match comparer(x.clone(), y.clone()) { diff --git a/src/fable-library-rust/src/NativeArray.rs b/src/fable-library-rust/src/NativeArray.rs index 9c3c80baf2..9faec9b9d7 100644 --- a/src/fable-library-rust/src/NativeArray.rs +++ b/src/fable-library-rust/src/NativeArray.rs @@ -1,5 +1,8 @@ pub mod NativeArray_ { - use crate::Native_::{alloc, mkRefMut, Lrc, LrcPtr, MutCell, Vec}; + use crate::Global_::SR::indexOutOfBounds; + use crate::Native_::{alloc, make_compare, mkRefMut, partial_compare, seq_to_iter}; + use crate::Native_::{Func1, Func2, Lrc, LrcPtr, MutCell, Seq, Vec}; + use crate::System::Collections::Generic::IComparer_1; // ----------------------------------------------------------- // Arrays @@ -39,7 +42,7 @@ pub mod NativeArray_ { impl Into> for Array { fn into(self) -> Vec { - self.get().iter().map(|item| item.clone()).collect() + self.get().iter().cloned().collect() } } @@ -51,6 +54,10 @@ pub mod NativeArray_ { array_from(a.to_vec()) } + pub fn new_init(value: &T, count: i32) -> Array { + array_from(alloc::vec![value.clone(); count as usize]) + } + pub fn new_empty() -> Array { array_from(Vec::new()) } @@ -59,35 +66,312 @@ pub mod NativeArray_ { array_from(Vec::with_capacity(capacity as usize)) } - pub fn new_init(value: &T, count: i32) -> Array { - array_from(alloc::vec![value.clone(); count as usize]) + pub fn new_from_enumerable(seq: Seq) -> Array { + array_from(Vec::from_iter(seq_to_iter(&seq))) } - pub fn new_copy(a: Array) -> Array { - array_from(a.to_vec()) + pub fn get_Capacity(a: Array) -> i32 { + a.capacity() as i32 + } + + pub fn get_Count(a: Array) -> i32 { + a.len() as i32 } pub fn isReadOnly(a: Array) -> bool { false } - pub fn count(a: Array) -> i32 { - a.len() as i32 + pub fn add(a: Array, v: T) { + a.get_mut().push(v); } - pub fn contains(a: Array, v: T) -> bool { - a.contains(&v) + pub fn addRange(a: Array, seq: Seq) { + let range = a.len()..a.len(); + a.get_mut().splice(range, seq_to_iter(&seq)); } - pub fn add(a: Array, v: T) { - a.get_mut().push(v); + pub fn copyTo(src: Array, dest: Array) { + copyTo2(src, dest, 0) + } + + pub fn copyTo2(src: Array, dest: Array, destIndex: i32) { + let count = src.len() as i32; + copyTo4(src, 0, dest, destIndex, count) + } + + pub fn copyTo4( + src: Array, + srcIndex: i32, + dest: Array, + destIndex: i32, + count: i32, + ) { + let check1 = srcIndex + count > src.len() as i32; + let check2 = destIndex + count > dest.len() as i32; + if srcIndex < 0 || destIndex < 0 || count < 0 || check1 || check2 { + panic!("{}", indexOutOfBounds()); + } + let rangeFrom = srcIndex as usize..(srcIndex + count) as usize; + let rangeTo = destIndex as usize..(destIndex + count) as usize; + dest.get_mut()[rangeTo].clone_from_slice(&src.as_slice()[rangeFrom]); } - pub fn remove(a: Array, pos: i32) -> bool { - a.get_mut().remove(pos as usize); true + pub fn contains(a: Array, v: T) -> bool { + a.contains(&v) } pub fn clear(a: Array) { a.get_mut().clear(); } + + pub fn convertAll( + a: Array, + converter: Func1, + ) -> Array { + let it = a.iter().map(|x| converter(x.clone())); + array_from(it.collect()) + } + + pub fn binarySearch(a: Array, v: T) -> i32 { + let res = a.binary_search_by(|x| partial_compare(x, &v)); + match res { + Ok(i) => i as i32, + Err(i) => !i as i32, + } + } + + pub fn binarySearch2( + a: Array, + v: T, + comparer: LrcPtr>, + ) -> i32 { + let cmp = make_compare(Func2::new(move |x: T, y: T| comparer.Compare(x, y))); + let res = a.binary_search_by(|x| cmp(x, &v)); + match res { + Ok(i) => i as i32, + Err(i) => !i as i32, + } + } + + pub fn binarySearch4( + a: Array, + index: i32, + count: i32, + v: T, + comparer: LrcPtr>, + ) -> i32 { + let len = a.len() as i32; + if index < 0 || index >= len || count < 0 || index + count > len { + panic!("{}", indexOutOfBounds()); + } + let range = index as usize..(index + count) as usize; + let cmp = make_compare(Func2::new(move |x: T, y: T| comparer.Compare(x, y))); + let res = a.as_slice()[range].binary_search_by(|x| cmp(x, &v)); + match res { + Ok(i) => (index as usize + i) as i32, + Err(i) => !(index as usize + i) as i32, + } + } + + pub fn exists(a: Array, predicate: Func1) -> bool { + a.iter().find(|&x| predicate(x.clone())).is_some() + } + + pub fn getRange(a: Array, index: i32, count: i32) -> Array { + let len = a.len() as i32; + if index < 0 || index >= len || count < 0 || index + count > len { + panic!("{}", indexOutOfBounds()); + } + let range = index as usize..(index + count) as usize; + array_from(a.as_slice()[range].to_vec()) + } + + pub fn forEach(a: Array, action: Func1) { + a.iter().for_each(|x| action(x.clone())); + } + + pub fn findAll(a: Array, predicate: Func1) -> Array { + let it = a.iter().filter(|&x| predicate(x.clone())); + array_from(it.cloned().collect()) + } + + pub fn find(a: Array, predicate: Func1) -> T { + let pos = a.iter().position(|x| predicate(x.clone())); + match pos { + Some(index) => a[index as i32].clone(), + None => T::default(), + } + } + + pub fn findLast(a: Array, predicate: Func1) -> T { + let pos = a.iter().rposition(|x| predicate(x.clone())); + match pos { + Some(index) => a[index as i32].clone(), + None => T::default(), + } + } + + pub fn findIndex(a: Array, predicate: Func1) -> i32 { + let mut it = a.iter(); + unwrap_pos(it.position(|x| predicate(x.clone()))) + } + + pub fn findLastIndex(a: Array, predicate: Func1) -> i32 { + let mut it = a.iter(); + unwrap_pos(it.rposition(|x| predicate(x.clone()))) + } + + fn unwrap_pos(pos: Option) -> i32 { + match pos { + Some(index) => index as i32, + None => -1, + } + } + + pub fn indexOf(a: Array, v: T) -> i32 { + let mut it = a.iter(); + unwrap_pos(it.position(|x| x.eq(&v))) + } + + pub fn indexOf2(a: Array, v: T, index: i32) -> i32 { + let len = a.len() as i32; + if index < 0 || index >= len { + panic!("{}", indexOutOfBounds()); + } + let mut it = a.iter().skip(index as usize); + unwrap_pos(it.position(|x| x.eq(&v)).map(|i| i + index as usize)) + } + + pub fn indexOf3(a: Array, v: T, index: i32, count: i32) -> i32 { + let len = a.len() as i32; + if index < 0 || index >= len || count < 0 || index + count > len { + panic!("{}", indexOutOfBounds()); + } + let mut it = a.iter().skip(index as usize).take(count as usize); + unwrap_pos(it.position(|x| x.eq(&v)).map(|i| i + index as usize)) + } + + pub fn lastIndexOf(a: Array, v: T) -> i32 { + let mut it = a.iter(); + unwrap_pos(it.rposition(|x| x.eq(&v))) + } + + pub fn lastIndexOf2(a: Array, v: T, index: i32) -> i32 { + lastIndexOf3(a, v, index, index + 1) + } + + pub fn lastIndexOf3(a: Array, v: T, index: i32, count: i32) -> i32 { + let len = a.len() as i32; + if index < 0 || index >= len || count < 0 || index + 1 < count { + panic!("{}", indexOutOfBounds()); + } + let start = index as usize + 1 - count as usize; + let mut it = a.iter().skip(start).take(count as usize); + unwrap_pos(it.rposition(|x| x.eq(&v)).map(|i| i + start)) + } + + pub fn insert(a: Array, pos: i32, v: T) { + a.get_mut().insert(pos as usize, v); + } + + pub fn insertRange(a: Array, index: i32, seq: Seq) { + let len = a.len() as i32; + if index < 0 || index >= len { + panic!("{}", indexOutOfBounds()); + } + let range = index as usize..index as usize; + a.get_mut().splice(range, seq_to_iter(&seq)); + } + + pub fn remove(a: Array, v: T) -> bool { + let pos = a.iter().position(|x| x.eq(&v)); + match pos { + Some(index) => { + a.get_mut().remove(index); + true + } + None => false, + } + } + + pub fn removeAt(a: Array, index: i32) { + let len = a.len() as i32; + if index < 0 || index >= len { + panic!("{}", indexOutOfBounds()); + } + a.get_mut().remove(index as usize); + } + + pub fn removeRange(a: Array, index: i32, count: i32) { + let len = a.len() as i32; + if index < 0 || index >= len || count < 0 || index + count > len { + panic!("{}", indexOutOfBounds()); + } + let range = index as usize..(index + count) as usize; + a.get_mut().splice(range, core::iter::empty::()); + } + + pub fn removeAll(a: Array, predicate: Func1) -> i32 { + let old_len = a.len(); + a.get_mut().retain(|x| !predicate(x.clone())); + (old_len - a.len()) as i32 + } + + pub fn reverse(a: Array) { + a.get_mut().reverse(); + } + + pub fn reverse2(a: Array, index: i32, count: i32) { + let len = a.len() as i32; + if index < 0 || index >= len || count < 0 || index + count > len { + panic!("{}", indexOutOfBounds()); + } + let range = index as usize..(index + count) as usize; + a.get_mut()[range].reverse(); + } + + pub fn slice(a: Array, index: i32, count: i32) -> Array { + getRange(a, index, count) + } + + pub fn sort(a: Array) { + a.get_mut().sort_by(partial_compare); + } + + pub fn sortBy(a: Array, comparer: Func2) { + a.get_mut().sort_by(make_compare(comparer)); + } + + pub fn sortWith(a: Array, comparer: LrcPtr>) { + let cmp = Func2::new(move |x: T, y: T| comparer.Compare(x, y)); + a.get_mut().sort_by(make_compare(cmp)); + } + + pub fn sortWith2( + a: Array, + index: i32, + count: i32, + comparer: LrcPtr>, + ) { + let len = a.len() as i32; + if index < 0 || index >= len || count < 0 || index + count > len { + panic!("{}", indexOutOfBounds()); + } + let range = index as usize..(index + count) as usize; + let cmp = Func2::new(move |x: T, y: T| comparer.Compare(x, y)); + a.get_mut()[range].sort_by(make_compare(cmp)); + } + + pub fn toArray(a: Array) -> Array { + array_from(a.to_vec()) + } + + pub fn trimExcess(a: Array) { + a.get_mut().shrink_to_fit(); + } + + pub fn trueForAll(a: Array, predicate: Func1) -> bool { + a.iter().all(|x| predicate(x.clone())) + } } diff --git a/tests/Rust/tests/src/ResizeArrayTests.fs b/tests/Rust/tests/src/ResizeArrayTests.fs index 397af01866..b921190397 100644 --- a/tests/Rust/tests/src/ResizeArrayTests.fs +++ b/tests/Rust/tests/src/ResizeArrayTests.fs @@ -32,31 +32,37 @@ let ``ResizeArray casting to seq works`` () = let xs = ResizeArray<_>(seq{1;2;3;4;5}) :> seq<_> Seq.sum xs |> equal 15 -// [] -// let ``ResizeArray iteration works`` () = -// let xs = ResizeArray<_>() -// xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) -// let mutable acc = 0. -// for i in xs do -// acc <- acc + i -// acc |> equal 15. - -// [] -// let ``ResizeArray iteration with index works`` () = -// let xs = ResizeArray<_>() -// for i = 1 to 4 do -// xs.Add(i) -// let mutable x = 0 -// for i = 0 to xs.Count - 1 do -// x <- x + xs[i] -// x |> equal 10 - -// [] -// let ``ResizeArray folding works`` () = -// let xs = ResizeArray<_>() -// xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) -// xs |> Seq.fold (fun acc item -> acc + item) 0. -// |> equal 15. +[] +let ``ResizeArray iteration works`` () = + let xs = ResizeArray<_>() + xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) + let mutable acc = 0. + for i in xs do + acc <- acc + i + acc |> equal 15. + +[] +let ``ResizeArray iteration with index works`` () = + let xs = ResizeArray<_>() + for i = 1 to 4 do + xs.Add(i) + let mutable x = 0 + for i = 0 to xs.Count - 1 do + x <- x + xs[i] + x |> equal 10 + +[] +let ``ResizeArray folding works`` () = + let xs = ResizeArray<_>() + xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) + let sum = xs |> Seq.fold (fun acc item -> acc + item) 0. + sum |> equal 15. + +[] +let ``ResizeArray.Capacity works`` () = + let xs = ResizeArray(42) + xs.Capacity |> equal 42 + xs.Count |> equal 0 [] let ``ResizeArray.Count works`` () = @@ -64,69 +70,69 @@ let ``ResizeArray.Count works`` () = xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) xs.Count |> equal 5 -// [] -// let ``ResizeArray.ConvertAll works`` () = -// let xs = ResizeArray<_> [1.; 2.; 3.; 4.] -// let ys = xs.ConvertAll(System.Converter(fun x -> int x)) -// ys |> Seq.toList |> equal [1;2;3;4] - -// [] -// let ``ResizeArray.Find works`` () = -// let xs = ResizeArray<_>() -// xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) -// System.Predicate<_> (fun x -> x = 1.) |> xs.Find |> equal 1. -// System.Predicate<_> (fun x -> x = -1.) |> xs.Find |> equal 0. - -// [] -// let ``ResizeArray.Find with option works`` () = -// let xs = ResizeArray<_>() -// xs.Add(Some 1); xs.Add(None); -// System.Predicate<_> (fun _ -> true) |> xs.Find |> equal (Some 1) -// System.Predicate<_> (fun _ -> false) |> xs.Find |> equal None -// System.Predicate<_> Option.isNone |> xs.Find |> equal None -// System.Predicate<_> Option.isSome |> xs.Find |> equal (Some 1) - -// [] -// let ``ResizeArray.FindAll works`` () = -// let xs = ResizeArray<_> [1.; 2.; 3.; 4.] -// System.Predicate<_> (fun x -> x <= 3.) |> xs.FindAll |> (fun l -> l.Count) |> equal 3 -// System.Predicate<_> (fun x -> x = 5.) |> xs.FindAll |> (fun l -> l.Count) |> equal 0 - -// [] -// let ``ResizeArray.FindLast works`` () = -// let xs = ResizeArray<_>() -// xs.Add(1.,0.); xs.Add(2.,0.); xs.Add(3.,0.); xs.Add(4.,0.); xs.Add(5.,0.); xs.Add(1.,1.) -// System.Predicate<_> (fun (x, _) -> x = 1.) |> xs.FindLast |> snd |> equal 1. - -// [] -// let ``ResizeArray.FindLast with option works`` () = -// let xs = ResizeArray<_>() -// xs.Add(Some 1); xs.Add(None); -// System.Predicate<_> (fun _ -> true) |> xs.FindLast |> equal None -// System.Predicate<_> (fun _ -> false) |> xs.FindLast |> equal None -// System.Predicate<_> Option.isSome |> xs.FindLast |> equal (Some 1) - -// [] -// let ``ResizeArray.FindIndex works`` () = -// let xs = ResizeArray<_>() -// xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(2.); xs.Add(5.) -// System.Predicate<_> (fun x -> x = 2.) |> xs.FindIndex |> equal 1 -// System.Predicate<_> (fun x -> x = 0.) |> xs.FindIndex |> equal -1 - -// [] -// let ``ResizeArray.FindLastIndex works`` () = -// let xs = ResizeArray<_>() -// xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(2.); xs.Add(5.) -// System.Predicate<_> (fun x -> x = 2.) |> xs.FindLastIndex |> equal 3 -// System.Predicate<_> (fun x -> x = 0.) |> xs.FindLastIndex |> equal -1 - -// [] -// let ``ResizeArray.ForEach works`` () = -// let xs = ResizeArray<_>() -// let mutable sum = 0 -// xs.Add(1); xs.Add(2); xs.Add(3); xs.Add(4); xs.Add(5) -// System.Action<_> (fun x -> sum <- sum + x) |> xs.ForEach -// sum |> equal 15 +[] +let ``ResizeArray.ConvertAll works`` () = + let xs = ResizeArray<_> [1.; 2.; 3.; 4.] + let ys = xs.ConvertAll(System.Converter(fun x -> int x)) + ys |> Seq.toList |> equal [1;2;3;4] + +[] +let ``ResizeArray.Find works`` () = + let xs = ResizeArray<_>() + xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) + System.Predicate<_> (fun x -> x = 1.) |> xs.Find |> equal 1. + System.Predicate<_> (fun x -> x = -1.) |> xs.Find |> equal 0. + +[] +let ``ResizeArray.Find with option works`` () = + let xs = ResizeArray<_>() + xs.Add(Some 1); xs.Add(None); + System.Predicate<_> (fun _ -> true) |> xs.Find |> equal (Some 1) + System.Predicate<_> (fun _ -> false) |> xs.Find |> equal None + System.Predicate<_> Option.isNone |> xs.Find |> equal None + System.Predicate<_> Option.isSome |> xs.Find |> equal (Some 1) + +[] +let ``ResizeArray.FindAll works`` () = + let xs = ResizeArray<_> [1.; 2.; 3.; 4.] + System.Predicate<_> (fun x -> x <= 3.) |> xs.FindAll |> (fun l -> l.Count) |> equal 3 + System.Predicate<_> (fun x -> x = 5.) |> xs.FindAll |> (fun l -> l.Count) |> equal 0 + +[] +let ``ResizeArray.FindLast works`` () = + let xs = ResizeArray<_>() + xs.Add(1.,0.); xs.Add(2.,0.); xs.Add(3.,0.); xs.Add(4.,0.); xs.Add(5.,0.); xs.Add(1.,1.) + System.Predicate<_> (fun (x, _) -> x = 1.) |> xs.FindLast |> snd |> equal 1. + +[] +let ``ResizeArray.FindLast with option works`` () = + let xs = ResizeArray<_>() + xs.Add(Some 1); xs.Add(None); + System.Predicate<_> (fun _ -> true) |> xs.FindLast |> equal None + System.Predicate<_> (fun _ -> false) |> xs.FindLast |> equal None + System.Predicate<_> Option.isSome |> xs.FindLast |> equal (Some 1) + +[] +let ``ResizeArray.FindIndex works`` () = + let xs = ResizeArray<_>() + xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(2.); xs.Add(5.) + System.Predicate<_> (fun x -> x = 2.) |> xs.FindIndex |> equal 1 + System.Predicate<_> (fun x -> x = 0.) |> xs.FindIndex |> equal -1 + +[] +let ``ResizeArray.FindLastIndex works`` () = + let xs = ResizeArray<_>() + xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(2.); xs.Add(5.) + System.Predicate<_> (fun x -> x = 2.) |> xs.FindLastIndex |> equal 3 + System.Predicate<_> (fun x -> x = 0.) |> xs.FindLastIndex |> equal -1 + +[] +let ``ResizeArray.ForEach works`` () = + let xs = ResizeArray<_>() + let mutable sum = 0 + xs.Add(1); xs.Add(2); xs.Add(3); xs.Add(4); xs.Add(5) + System.Action<_> (fun x -> sum <- sum + x) |> xs.ForEach + sum |> equal 15 [] let ``ResizeArray indexer getter works`` () = @@ -139,7 +145,7 @@ let ``ResizeArray indexer setter works`` () = let xs = ResizeArray<_>() xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) xs[3] <- 10. - xs[3] |> equal 10. + xs.ToArray() |> equal [|1.;2.;3.;10.;5.|] [] let ``ResizeArray.Clear works`` () = @@ -152,29 +158,38 @@ let ``ResizeArray.Clear works`` () = let ``ResizeArray.Add works`` () = let xs = ResizeArray<_>() xs.Add(1.); xs.Add(2.); xs.Add(3.) - equal 3 xs.Count - -// [] -// let ``ResizeArray.AddRange works`` () = -// let xs = ResizeArray<_>() -// xs.AddRange [1;2;3] -// equal 3 xs.Count - -// [] -// let ``ResizeArray.InsertRange works`` () = -// let xs = ResizeArray<_>() -// let mutable sum = 0 -// xs.Add(1); xs.Add(2); xs.Add(5) -// xs.InsertRange(2, [3;4]) -// Seq.toList xs |> equal [1;2;3;4;5] - -// [] -// let ``ResizeArray.GetRange works`` () = -// let xs = ResizeArray<_>() -// xs.AddRange [1;2;3] -// let sub = xs.GetRange(1, 2) -// sub.Count |> equal 2 -// sub.Contains(1) |> equal false + xs.ToArray() |> equal [|1;2;3|] + +[] +let ``ResizeArray.AddRange works`` () = + let xs = ResizeArray<_>() + xs.AddRange [1;2;3] + xs.ToArray() |> equal [|1;2;3|] + +[] +let ``ResizeArray.Insert works`` () = + let xs = ResizeArray<_>([|1;2;3;4;5|]) + xs.Insert(2, 8) + xs.ToArray() |> equal [|1;2;8;3;4;5|] + +[] +let ``ResizeArray.InsertRange works`` () = + let xs = ResizeArray<_>() + xs.Add(1); xs.Add(2); xs.Add(5) + xs.InsertRange(2, [3;4]) + xs.ToArray() |> equal [|1;2;3;4;5|] + +[] +let ``ResizeArray.GetRange works`` () = + let xs = ResizeArray<_>([|1;2;3;4;5|]) + let ys = xs.GetRange(1, 2) + ys.ToArray() |> equal [|2;3|] + +[] +let ``ResizeArray.Slice works`` () = + let xs = ResizeArray<_>([|1;2;3;4;5|]) + let ys = xs.Slice(1, 2) + ys.ToArray() |> equal [|2;3|] [] let ``ResizeArray.Contains works`` () = @@ -186,38 +201,58 @@ let ``ResizeArray.Contains works`` () = [] let ``ResizeArray.IndexOf works`` () = + let xs = ResizeArray<_>([|3;2;1;3;2|]) + xs.IndexOf(2) |> equal 1 + xs.IndexOf(3) |> equal 0 + xs.IndexOf(4) |> equal -1 + +[] +let ``ResizeArray.IndexOf works II`` () = + let xs = ResizeArray<_>([|"T";"A";"M";"B";"D";"T";"C"|]) + xs.IndexOf("T") |> equal 0 + xs.IndexOf("T", 3) |> equal 5 + xs.IndexOf("T", 2, 2) |> equal -1 + +[] +let ``ResizeArray.LastIndexOf works`` () = + let xs = ResizeArray<_>([|3;2;1;3;2|]) + xs.LastIndexOf(2) |> equal 4 + xs.LastIndexOf(3) |> equal 3 + xs.LastIndexOf(4) |> equal -1 + +[] +let ``ResizeArray.LastIndexOf works II`` () = + let xs = ResizeArray<_>([|"T";"A";"M";"B";"D";"T";"C"|]) + xs.LastIndexOf("T") |> equal 5 + xs.LastIndexOf("T", 3) |> equal 0 + xs.LastIndexOf("T", 4, 4) |> equal -1 + +[] +let ``ResizeArray.Remove works`` () = + let xs = ResizeArray<_>() + xs.Add("ab") + xs.Add("ch") + xs.Remove("ab") |> equal true + xs.Remove("cd") |> equal false + +[] +let ``ResizeArray.RemoveAll works`` () = let xs = ResizeArray<_>() + xs.Add("ab") xs.Add("ch") xs.Add("ab") - xs.IndexOf("ab") |> equal 1 - xs.IndexOf("cd") |> equal -1 - -// [] -// let ``ResizeArray.Remove works`` () = -// let xs = ResizeArray<_>() -// xs.Add("ab") -// xs.Add("ch") -// xs.Remove("ab") |> equal true -// xs.Remove("cd") |> equal false - -// [] -// let ``ResizeArray.RemoveAll works`` () = -// let xs = ResizeArray<_>() -// xs.Add("ab") -// xs.Add("ch") -// xs.Add("ab") -// System.Predicate<_> (fun x -> x = "ab") |> xs.RemoveAll |> equal 2 -// System.Predicate<_> (fun x -> x = "ab") |> xs.RemoveAll |> equal 0 -// xs[0] |> equal "ch" - -// [] -// let ``ResizeArray.RemoveRange works`` () = -// let xs = ResizeArray() -// for x in [1 .. 5] do xs.Add(x) -// xs.RemoveRange(1, 2) // [1;2;3;4;5] -> [1;4;5] -// equal 1 xs[0] -// equal 4 xs[1] -// equal 5 xs[2] + System.Predicate<_> (fun x -> x = "ab") |> xs.RemoveAll |> equal 2 + System.Predicate<_> (fun x -> x = "ab") |> xs.RemoveAll |> equal 0 + xs[0] |> equal "ch" + +[] +let ``ResizeArray.RemoveRange works`` () = + let xs = ResizeArray() + for x in [1 .. 5] do xs.Add(x) + xs.RemoveRange(1, 2) // [1;2;3;4;5] -> [1;4;5] + equal 1 xs[0] + equal 4 xs[1] + equal 5 xs[2] [] let ``ResizeArray.Exists works`` () = @@ -235,81 +270,134 @@ let ``ResizeArray.RemoveAt works`` () = let xs = ResizeArray<_>() xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) xs.RemoveAt(2) - xs.Count |> equal 4 - xs[2] |> equal 4. + xs.ToArray() |> equal [|1.;2.;4.;5.|] [] -let ``ResizeArray.Insert works`` () = - let xs = ResizeArray<_>() - xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) - xs.Insert(2, 8.) - xs.Count |> equal 6 - xs[2] |> equal 8. - -[] -let ``ResizeArray.ReverseInPlace works`` () = +let ``ResizeArray.Reverse works`` () = let xs = ResizeArray<_>() xs.Add(1.); xs.Add(2.); xs.Add(3.); xs.Add(4.); xs.Add(5.) xs.Reverse() xs.ToArray() |> equal [|5.;4.;3.;2.;1.|] [] -let ``ResizeArray.SortInPlace works`` () = +let ``ResizeArray.Reverse works II`` () = + let xs = ResizeArray<_>([|1;2;3;4;5|]) + xs.Reverse(2, 3) + xs.Reverse(1, 2) + xs.ToArray() |> equal [|1;5;2;4;3|] + +[] +let ``ResizeArray.Sort works`` () = let xs = ResizeArray<_>() xs.Add("Ana"); xs.Add("Pedro"); xs.Add("Lucía"); xs.Add("Paco") xs.Sort() xs.ToArray() |> equal [|"Ana";"Lucía";"Paco";"Pedro"|] [] -let ``ResizeArray.SortInPlace works II`` () = +let ``ResizeArray.Sort works II`` () = let xs = ResizeArray [1;3;10;2] xs.Sort() xs.ToArray() |> equal [|1;2;3;10|] [] -let ``ResizeArray.SortInPlace works III`` () = +let ``ResizeArray.Sort works III`` () = let xs = ResizeArray [1.;3.;10.;2.] xs.Sort() xs.ToArray() |> equal [|1.;2.;3.;10.|] [] -let ``ResizeArray.SortInPlaceWith works`` () = +let ``ResizeArray.Sort works with custom comparison`` () = let xs = ResizeArray<_>() xs.Add(3.); xs.Add(6.); xs.Add(5.); xs.Add(4.); xs.Add(8.) xs.Sort(fun x y -> if x > y then -1 elif x < y then 1 else 0) xs.ToArray() |> equal [|8.;6.;5.;4.;3.|] [] -let ``ResizeArray.SortInPlaceWith works with custom comparison function`` () = // See #1386 - let xs = ResizeArray [1;3;2] +let ``ResizeArray.Sort works with custom comparison II`` () = // See #1386 + let xs = ResizeArray [1;5;2;3;4] xs.Sort(fun x y -> if x < y then 1 else -1) - xs.ToArray() |> equal [|3;2;1|] + xs.ToArray() |> equal [|5;4;3;2;1|] xs.Sort(compare) - xs.ToArray() |> equal [|1;2;3|] + xs.ToArray() |> equal [|1;2;3;4;5|] -// [] -// let ``ResizeArray.SortInPlaceWith works with custom comparer`` () = // See #1386 -// let xs = ResizeArray [1;3;2] -// let comparer = System.Collections.Generic.Comparer.Default -// xs.Sort(comparer) -// Seq.toList xs |> equal [1;2;3] +[] +let ``ResizeArray.Sort works with custom comparer`` () = // See #1386 + let xs = ResizeArray<_> [|1;5;2;3;4|] + let comparer = System.Collections.Generic.Comparer.Default + xs.Sort(comparer) + xs.ToArray() |> equal [|1;2;3;4;5|] + +[] +let ``ResizeArray.Sort works with custom comparer II`` () = // See #1386 + let xs = ResizeArray<_> [|1;5;2;3;4|] + let comparer = System.Collections.Generic.Comparer.Default + xs.Sort(1,3, comparer) + xs.ToArray() |> equal [|1;2;3;5;4|] [] let ``ResizeArray.ToArray works`` () = let xs = ResizeArray<_>() xs.Add(3.); xs.Add(6.); xs.Add(5.); xs.Add(4.); xs.Add(8.) xs.Count |> equal 5 - let ar = xs.ToArray() - Array.length ar |> equal 5 - ar[0] <- 2. - equal 3. xs[0] - equal 2. ar[0] - -[] -let ``ResizeArray.Item is undefined when index is out of range`` () = - let xs = ResizeArray [0] -#if FABLE_COMPILER_JAVASCRIPT - isNull <| box (xs.Item 1) |> equal true -#else - throwsAnyError (fun () -> (xs.Item 1) |> ignore) -#endif + xs.ToArray() |> equal [|3.;6.;5.;4.;8.|] + +[] +let ``ResizeArray.TrimExcess works`` () = + let xs = ResizeArray<_>(42) + xs.Add(3.); xs.Add(6.); xs.Add(5.); xs.Add(4.); xs.Add(8.) + xs.TrimExcess() + xs.Count |> equal 5 + xs.Capacity |> equal 5 + +[] +let ``ResizeArray.TrueForAll works`` () = + let xs = ResizeArray() + for x = 1 to 5 do xs.Add(x) + xs.TrueForAll (fun a -> a < 6) |> equal true + xs.TrueForAll (fun a -> a > 5) |> equal false + +[] +let ``ResizeArray.Item throws when index is out of range`` () = + let xs = ResizeArray [|1;2;3|] + throwsAnyError (fun () -> (xs.Item 3) |> ignore) + +[] +let ``ResizeArray.BinarySearch works`` () = + let xs = ResizeArray [|1;4;5;7;10;13|] + xs.BinarySearch(7) |> equal 3 + xs.BinarySearch(8) |> equal ~~~4 + +[] +let ``ResizeArray.BinarySearch works II`` () = + let xs = ResizeArray [|1;4;5;7;10;13|] + let comparer = System.Collections.Generic.Comparer.Default + xs.BinarySearch(7, comparer) |> equal 3 + xs.BinarySearch(8, comparer) |> equal ~~~4 + +[] +let ``ResizeArray.BinarySearch works III`` () = + let xs = ResizeArray [|1;4;5;7;10;13|] + let comparer = System.Collections.Generic.Comparer.Default + xs.BinarySearch(1, 3, 7, comparer) |> equal 3 + xs.BinarySearch(1, 2, 8, comparer) |> equal ~~~3 + +[] +let ``ResizeArray.CopyTo works`` () = + let xs = ResizeArray<_> [|1;2;3;4|] + let ys = [|5;6;7;8;9|] + xs.CopyTo(ys) + ys |> equal [|1;2;3;4;9|] + +[] +let ``ResizeArray.CopyTo works II`` () = + let xs = ResizeArray<_> [|1;2;3;4|] + let ys = [|5;6;7;8;9|] + xs.CopyTo(ys, 1) + ys |> equal [|5;1;2;3;4|] + +[] +let ``ResizeArray.CopyTo works III`` () = + let xs = ResizeArray<_> [|1;2;3;4|] + let ys = [|5;6;7;8;9|] + xs.CopyTo(2, ys, 1, 2) + ys |> equal [|5;3;4;8;9|]