Skip to content

Commit

Permalink
[Rust] Added Guid.TryParse, Guid.ToByteArray (#3585)
Browse files Browse the repository at this point in the history
  • Loading branch information
ncave authored Nov 8, 2023
1 parent 0be4ca6 commit 585a73d
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 110 deletions.
4 changes: 4 additions & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

#### Rust

* Added `Guid.TryParse`, `Guid.ToByteArray` (by @ncave)

## 4.5.0 - 2023-11-07

### Changed
Expand Down
12 changes: 8 additions & 4 deletions src/Fable.Transforms/Rust/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2739,15 +2739,19 @@ let guids (com: ICompiler) (ctx: Context) (r: SourceLocation option) t (i: CallI
match i.CompiledName, thisArg, args with
| ".ctor", None, _ ->
match args with
| [] -> Helper.LibCall(com, "Guid", "empty", t, [], ?loc=r) |> Some
| [ExprType String] -> Helper.LibCall(com, "Guid", "parse", t, args, ?loc=r) |> Some
| [] ->
Helper.LibCall(com, "Guid", "empty", t, [], ?loc=r) |> Some
| [ExprType String] ->
Helper.LibCall(com, "Guid", "parse", t, args, ?loc=r) |> Some
| [ExprType(Array(Number(UInt8, _), _))] ->
Helper.LibCall(com, "Guid", "new_from_array", t, args, ?loc=r) |> Some
// TODO: other constructor overrides
| _ -> None
// | "Empty", None, [] -> // it's a static field, see tryField
| "NewGuid", None, [] -> Helper.LibCall(com, "Guid", "new_guid", t, args, ?loc=r) |> Some
| "Parse", None, [ExprType String] -> Helper.LibCall(com, "Guid", "parse", t, args, ?loc=r) |> Some
// | None, "TryParse", _ -> Helper.LibCall(com, "Guid", "try_parse", t, args, ?loc=r) |> Some
// | Some x, "ToByteArray", [] -> Helper.LibCall(com, "Guid", "to_byte_array", t, args, ?loc=r) |> Some
| "TryParse", None, [ExprType String; _] -> Helper.LibCall(com, "Guid", "tryParse", t, args, ?loc=r) |> Some
| "ToByteArray", Some x, [] -> Helper.LibCall(com, "Guid", "toByteArray", t, [x], ?loc=r) |> Some
| "ToString", Some x, [] -> toString com ctx r [x] |> Some
// TODO: other methods and overrides
| _ -> None
Expand Down
2 changes: 1 addition & 1 deletion src/fable-library-rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ num-integer = { version = "0.1", optional = true }
num-traits = { version = "0.2", optional = true }
rust_decimal = { version = "1.32", features = ["maths"], default-features = false, optional = true }
futures = { version = "0.3", features = ["executor", "thread-pool"], optional = true }
uuid = { version = "1.4", features = ["v4"], default-features = false, optional = true }
uuid = { version = "1.5", features = ["v4"], default-features = false, optional = true }
chrono = { version = "0.4", optional = true }
regex = { version = "1.9", optional = true }

Expand Down
29 changes: 24 additions & 5 deletions src/fable-library-rust/src/Guid.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#[cfg(feature = "guid")]
pub mod Guid_ {
use crate::Native_::compare;
use crate::NativeArray_::{new_array, Array};
use crate::Native_::{compare, MutCell};
use crate::String_::{string, toString};
use uuid::{Uuid};
use uuid::Uuid;

#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
pub struct Guid(Uuid);
Expand All @@ -27,10 +28,28 @@ pub mod Guid_ {
Guid(Uuid::new_v4())
}

pub fn new_from_array(a: Array<u8>) -> Guid {
Guid(Uuid::from_slice_le(a.as_slice()).unwrap())
}

pub fn tryParse(s: string, res: &MutCell<Guid>) -> bool {
match Uuid::parse_str(s.trim()) {
Ok(uuid) => {
res.set(Guid(uuid));
true
}
Err(e) => false,
}
}

pub fn parse(s: string) -> Guid {
match Uuid::parse_str(s.as_ref()) {
Ok(res) => Guid(res),
Err(x) => panic!("{}", x)
match Uuid::parse_str(s.trim()) {
Ok(uuid) => Guid(uuid),
Err(e) => panic!("{}", e),
}
}

pub fn toByteArray(x: Guid) -> Array<u8> {
new_array(&x.0.to_bytes_le())
}
}
6 changes: 3 additions & 3 deletions tests/Js/Main/ConvertTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1169,16 +1169,16 @@ let tests =
let upperGuid = Guid.Parse upper
lowerGuid = upperGuid |> equal true

testCase "Convert Guid to byte[] works" <| fun () ->
testCase "Convert Guid to byte array works" <| fun () ->
let g = Guid.Parse("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
let g2 = Guid.Parse(id "96258006-c4ba-4a7f-80c4-de7f2b2898c5")

g.ToByteArray() |> equal [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]
g2.ToByteArray() |> equal [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]

testCase "Convert byte[] to Guid works" <| fun () ->
testCase "Convert byte array to Guid works" <| fun () ->
let g = Guid [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]
g.ToString() |> equal("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
g.ToString() |> equal "96258006-c4ba-4a7f-80c4-de7f2b2898c5"

testCase "Guid.ToString works with formats" <| fun () ->
let g = Guid.Parse("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
Expand Down
6 changes: 3 additions & 3 deletions tests/Python/TestGuid.fs
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,16 @@ let ``test Parsed guids with different case are considered the same`` () = // Se
lowerGuid = upperGuid |> equal true

[<Fact>]
let ``test Convert Guid to byte[] works`` () =
let ``test Convert Guid to byte array works`` () =
let g = Guid.Parse("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
let g2 = Guid.Parse(id "96258006-c4ba-4a7f-80c4-de7f2b2898c5")
g.ToByteArray() |> equal [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]
g2.ToByteArray() |> equal [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]

[<Fact>]
let ``test Convert byte[] to Guid works`` () =
let ``test Convert byte array to Guid works`` () =
let g = Guid [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]
g.ToString() |> equal("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
g.ToString() |> equal "96258006-c4ba-4a7f-80c4-de7f2b2898c5"

// [<Fact>]
// let ``Guid.ToString works with formats`` () =
Expand Down
182 changes: 88 additions & 94 deletions tests/Rust/tests/src/GuidTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ let ``Guid.NewGuid creates different guids`` () =
let g2 = Guid.NewGuid()
g = g2 |> equal false

[<Fact>]
let ``Guid.Parse works`` () =
let s = "f46d24f0-183e-4fca-9f47-e382afdfde8b"
let g = Guid.Parse(s)
g.ToString() |> equal s

[<Fact>]
let ``Guid equality works`` () =
let s = "f46d24f0-183e-4fca-9f47-e382afdfde8b"
Expand All @@ -42,103 +36,103 @@ let ``Guid.ToString works`` () =
let g = Guid.Parse("a3cc8928-7148-43e2-a863-a3954aea02df")
g.ToString() |> equal "a3cc8928-7148-43e2-a863-a3954aea02df"

// [<Fact>]
// let ``Guid.NewGuid works`` () =
// let g1 = Guid.NewGuid()
// let g2 = Guid.NewGuid()
// g1 = g2 |> equal false
// let s1 = string g1
// equal 36 s1.Length
// Text.RegularExpressions.Regex.IsMatch(
// s1, "^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$")
// |> equal true
// let g3 = Guid.Parse s1
// g1 = g3 |> equal true
[<Fact>]
let ``Guid.NewGuid works`` () =
let g1 = Guid.NewGuid()
let g2 = Guid.NewGuid()
g1 = g2 |> equal false
let s1 = string g1
equal 36 s1.Length
Text.RegularExpressions.Regex.IsMatch(
s1, "^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$")
|> equal true
let g3 = Guid.Parse s1
g1 = g3 |> equal true

// // id is prefixed for guid creation as we check at compile time (if able) to create a string const
// [<Fact>]
// let ``Guid.Parse works`` () =
// let guids = [
// Guid.Parse("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
// Guid.Parse(id "96258006-c4ba-4a7f-80c4-de7f2b2898c5")
// Guid.Parse("96258006c4ba4a7f80c4de7f2b2898c5")
// Guid.Parse(id "96258006c4ba4a7f80c4de7f2b2898c5")
// Guid.Parse("{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
// Guid.Parse(id "{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
// Guid.Parse("(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid.Parse(id "(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid.Parse("{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
// Guid.Parse(id "{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
// Guid("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
// Guid(id "96258006-c4ba-4a7f-80c4-de7f2b2898c5")
// Guid("96258006c4ba4a7f80c4de7f2b2898c5")
// Guid(id "96258006c4ba4a7f80c4de7f2b2898c5")
// Guid("{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
// Guid(id "{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
// Guid("(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid(id "(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid("{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
// Guid(id "{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
// ]
// guids
// |> List.iter (fun g -> g.ToString() |> equal "96258006-c4ba-4a7f-80c4-de7f2b2898c5")
// id is prefixed for guid creation as we check at compile time (if able) to create a string const
[<Fact>]
let ``Guid.Parse works`` () =
let guids = [
Guid.Parse("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
Guid.Parse(id "96258006-c4ba-4a7f-80c4-de7f2b2898c5")
Guid.Parse("96258006c4ba4a7f80c4de7f2b2898c5")
Guid.Parse(id "96258006c4ba4a7f80c4de7f2b2898c5")
Guid.Parse("{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
Guid.Parse(id "{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
// Guid.Parse("(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid.Parse(id "(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid.Parse("{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
// Guid.Parse(id "{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
Guid("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
Guid(id "96258006-c4ba-4a7f-80c4-de7f2b2898c5")
Guid("96258006c4ba4a7f80c4de7f2b2898c5")
Guid(id "96258006c4ba4a7f80c4de7f2b2898c5")
Guid("{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
Guid(id "{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
// Guid("(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid(id "(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid("{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
// Guid(id "{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
]
guids
|> List.iter (fun g -> g.ToString() |> equal "96258006-c4ba-4a7f-80c4-de7f2b2898c5")

[<Fact>]
let ``Guid.Parse fails if string is not well formed`` () =
throwsAnyError (fun () -> Guid.Parse(id "foo"))

// [<Fact>]
// let ``Guid.TryParse works`` () =
// let successGuids = [
// Guid.TryParse("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
// Guid.TryParse(id "96258006-c4ba-4a7f-80c4-de7f2b2898c5")
// Guid.TryParse("96258006c4ba4a7f80c4de7f2b2898c5")
// Guid.TryParse(id "96258006c4ba4a7f80c4de7f2b2898c5")
// Guid.TryParse("{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
// Guid.TryParse(id "{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
// Guid.TryParse("(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid.TryParse(id "(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid.TryParse("{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
// Guid.TryParse(id "{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
// ]
// let failGuids = [
// Guid.TryParse("96258006-c4ba-4a7f-80c4")
// Guid.TryParse(id "96258006-c4ba-4a7f-80c4")
// Guid.TryParse("96258007f80c4de7f2b2898c5")
// Guid.TryParse(id "96258007f80c4de7f2b2898c5")
// Guid.TryParse("{96258006-c4ba-4a7f-80c4}")
// Guid.TryParse(id "{96258006-c4ba-4a7f-80c4}")
// Guid.TryParse("(96258006-c4ba-80c4-de7f2b2898c5)")
// Guid.TryParse(id "(96258006-c4ba-80c4-de7f2b2898c5)")
// Guid.TryParse("{0x96258006,0xc4ba,{0x80,0xc4,0xde,0x7f,0x28,0x98,0xc5}}")
// Guid.TryParse(id "{0x96258006,0xc4ba,{0x80,0xc4,0xde,0x7f,0x28,0x98,0xc5}}")
// ]
// successGuids
// |> List.iter (fst >> (equal true))
// failGuids
// |> List.iter (fst >> (equal false))
[<Fact>]
let ``Guid.TryParse works`` () =
let successGuids = [
Guid.TryParse("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
Guid.TryParse(id "96258006-c4ba-4a7f-80c4-de7f2b2898c5")
Guid.TryParse("96258006c4ba4a7f80c4de7f2b2898c5")
Guid.TryParse(id "96258006c4ba4a7f80c4de7f2b2898c5")
Guid.TryParse("{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
Guid.TryParse(id "{96258006-c4ba-4a7f-80c4-de7f2b2898c5}")
// Guid.TryParse("(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid.TryParse(id "(96258006-c4ba-4a7f-80c4-de7f2b2898c5)")
// Guid.TryParse("{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
// Guid.TryParse(id "{0x96258006,0xc4ba,0x4a7f,{0x80,0xc4,0xde,0x7f,0x2b,0x28,0x98,0xc5}}")
]
let failGuids = [
Guid.TryParse("96258006-c4ba-4a7f-80c4")
Guid.TryParse(id "96258006-c4ba-4a7f-80c4")
Guid.TryParse("96258007f80c4de7f2b2898c5")
Guid.TryParse(id "96258007f80c4de7f2b2898c5")
Guid.TryParse("{96258006-c4ba-4a7f-80c4}")
Guid.TryParse(id "{96258006-c4ba-4a7f-80c4}")
// Guid.TryParse("(96258006-c4ba-80c4-de7f2b2898c5)")
// Guid.TryParse(id "(96258006-c4ba-80c4-de7f2b2898c5)")
// Guid.TryParse("{0x96258006,0xc4ba,{0x80,0xc4,0xde,0x7f,0x28,0x98,0xc5}}")
// Guid.TryParse(id "{0x96258006,0xc4ba,{0x80,0xc4,0xde,0x7f,0x28,0x98,0xc5}}")
]
successGuids
|> List.iter (fst >> (equal true))
failGuids
|> List.iter (fst >> (equal false))

// [<Fact>]
// let ``Parsed guids with different case are considered the same`` () = // See #1718
// let aGuid = Guid.NewGuid()
// let lower = aGuid.ToString().ToLower()
// let upper = aGuid.ToString().ToUpper()
// lower = upper |> equal false
// let lowerGuid = Guid.Parse lower
// let upperGuid = Guid.Parse upper
// lowerGuid = upperGuid |> equal true
[<Fact>]
let ``Parsed guids with different case are considered the same`` () = // See #1718
let aGuid = Guid.NewGuid()
let lower = aGuid.ToString().ToLower()
let upper = aGuid.ToString().ToUpper()
lower = upper |> equal false
let lowerGuid = Guid.Parse lower
let upperGuid = Guid.Parse upper
lowerGuid = upperGuid |> equal true

// [<Fact>]
// let ``Convert Guid to byte[] works`` () =
// let g = Guid.Parse("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
// let g2 = Guid.Parse(id "96258006-c4ba-4a7f-80c4-de7f2b2898c5")
// g.ToByteArray() |> equal [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]
// g2.ToByteArray() |> equal [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]
[<Fact>]
let ``Convert Guid to byte array works`` () =
let g = Guid.Parse("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
let g2 = Guid.Parse(id "96258006-c4ba-4a7f-80c4-de7f2b2898c5")
g.ToByteArray() |> equal [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]
g2.ToByteArray() |> equal [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]

// [<Fact>]
// let ``Convert byte[] to Guid works`` () =
// let g = Guid [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]
// g.ToString() |> equal("96258006-c4ba-4a7f-80c4-de7f2b2898c5")
[<Fact>]
let ``Convert byte array to Guid works`` () =
let g = Guid [|6uy; 128uy; 37uy; 150uy; 186uy; 196uy; 127uy; 74uy; 128uy; 196uy; 222uy; 127uy; 43uy; 40uy; 152uy; 197uy|]
g.ToString() |> equal "96258006-c4ba-4a7f-80c4-de7f2b2898c5"

// [<Fact>]
// let ``Guid.ToString works with formats`` () =
Expand Down

0 comments on commit 585a73d

Please sign in to comment.