1 // Copyright 2023> Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8 
9 use std::{env, process};
10 use uguid::Guid;
11 
12 const USAGE: &str = r#"
13 usage: guid_info <guid>
14 the <guid> format is "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
15 where each `x` is a hex digit (any of `0-9`, `a-f`, or `A-F`).
16 "#;
17 
format_bytes(bytes: &[u8]) -> String18 fn format_bytes(bytes: &[u8]) -> String {
19     let mut s = String::new();
20     for (i, byte) in bytes.iter().enumerate() {
21         if i != 0 && (i % 2) == 0 {
22             s.push(' ');
23         }
24         s += &format!("{byte:02x}");
25     }
26     s
27 }
28 
format_guid(guid: Guid) -> String29 fn format_guid(guid: Guid) -> String {
30     format!(
31         "guid: {guid}
32   version: {version}
33   variant: {variant:?}
34   time_low: {time_low}
35   time_mid: {time_mid}
36   time_high_and_version: {time_high_and_version}
37   clock_seq_high_and_reserved: {clock_seq_high_and_reserved}
38   clock_seq_low: {clock_seq_low}
39   node: {node}",
40         version = guid.version(),
41         variant = guid.variant(),
42         time_low = format_bytes(&guid.time_low()),
43         time_mid = format_bytes(&guid.time_mid()),
44         time_high_and_version = format_bytes(&guid.time_high_and_version()),
45         clock_seq_high_and_reserved =
46             format_bytes(&[guid.clock_seq_high_and_reserved()]),
47         clock_seq_low = format_bytes(&[guid.clock_seq_low()]),
48         node = format_bytes(&guid.node())
49     )
50 }
51 
main()52 fn main() {
53     let args: Vec<_> = env::args().collect();
54     if args.len() != 2 {
55         println!("{}", USAGE.trim());
56         process::exit(1);
57     }
58 
59     let arg = &args[1];
60     match arg.parse::<Guid>() {
61         Ok(guid) => {
62             println!("{}", format_guid(guid));
63         }
64         Err(err) => {
65             println!("invalid input: {err}");
66             process::exit(1);
67         }
68     }
69 }
70 
71 #[cfg(test)]
72 mod tests {
73     use super::*;
74 
75     #[test]
test_format_bytes()76     fn test_format_bytes() {
77         assert_eq!(format_bytes(&[]), "");
78         assert_eq!(format_bytes(&[0]), "00");
79         assert_eq!(format_bytes(&[0x12, 0x34]), "1234");
80         assert_eq!(format_bytes(&[0x12, 0x34, 0x56, 0x78]), "1234 5678");
81     }
82 }
83