@@ -9,6 +9,22 @@ use regex::Regex;
9
9
use serde:: { de:: Error , Deserialize , Deserializer , Serialize , Serializer } ;
10
10
use std:: { cmp, ops:: Deref , str:: FromStr , sync:: OnceLock } ;
11
11
12
+ // Reference: https://github.com/bluesky-social/indigo/blob/9e3b84fdbb20ca4ac397a549e1c176b308f7a6e1/repo/tid.go#L11-L19
13
+ fn s32_encode ( mut i : u64 ) -> String {
14
+ const S32_CHAR : & [ u8 ] = b"234567abcdefghijklmnopqrstuvwxyz" ;
15
+
16
+ let mut s = String :: new ( ) ;
17
+ for _ in 0 ..13 {
18
+ let c = i & 0x1F ;
19
+ s. push ( S32_CHAR [ c as usize ] as char ) ;
20
+
21
+ i >>= 5 ;
22
+ }
23
+
24
+ // Reverse the string to convert it to big-endian format.
25
+ s. as_str ( ) . chars ( ) . rev ( ) . collect ( )
26
+ }
27
+
12
28
/// Common trait implementations for Lexicon string formats that are newtype wrappers
13
29
/// around `String`.
14
30
macro_rules! string_newtype {
@@ -410,7 +426,7 @@ impl Serialize for Language {
410
426
411
427
/// A [Timestamp Identifier].
412
428
///
413
- /// [Timestamp Identifier]: https://atproto.com/specs/record-key#record-key-type- tid
429
+ /// [Timestamp Identifier]: https://atproto.com/specs/tid
414
430
#[ derive( Clone , Debug , PartialEq , Eq , Serialize , Hash ) ]
415
431
#[ serde( transparent) ]
416
432
pub struct Tid ( String ) ;
@@ -436,6 +452,19 @@ impl Tid {
436
452
}
437
453
}
438
454
455
+ /// Construct a new timestamp with the specified clock ID.
456
+ ///
457
+ /// Clock IDs 0-31 can be used as an ad-hoc clock ID if you are not concerned
458
+ /// with this parameter.
459
+ pub fn now ( cid : u32 ) -> Self {
460
+ let now = chrono:: Utc :: now ( ) . timestamp_micros ( ) as u64 ;
461
+
462
+ // The TID is laid out as follows:
463
+ // 0TTTTTTTTTTTTTTT TTTTTTTTTTTTTTTT TTTTTTTTTTTTTTTT TTTTTTCCCCCCCCCC
464
+ let tid = ( now << 10 ) & 0x7FFF_FFFF_FFFF_FC00 | ( cid as u64 ) & 0x3FF ;
465
+ Self ( s32_encode ( tid) )
466
+ }
467
+
439
468
/// Returns the TID as a string slice.
440
469
pub fn as_str ( & self ) -> & str {
441
470
self . 0 . as_str ( )
@@ -766,6 +795,12 @@ mod tests {
766
795
}
767
796
}
768
797
798
+ #[ test]
799
+ fn tid_encode ( ) {
800
+ assert_eq ! ( s32_encode( 0 ) , "2222222222222" ) ;
801
+ assert_eq ! ( s32_encode( 1 ) , "2222222222223" ) ;
802
+ }
803
+
769
804
#[ test]
770
805
fn valid_tid ( ) {
771
806
for valid in [ "3jzfcijpj2z2a" , "7777777777777" , "3zzzzzzzzzzzz" ] {
0 commit comments