LCOV - code coverage report
Current view: top level - libs/utils/src - id.rs (source / functions) Coverage Total Hit
Test: 1b0a6a0c05cee5a7de360813c8034804e105ce1c.info Lines: 85.2 % 244 208
Test Date: 2025-03-12 00:01:28 Functions: 45.3 % 159 72

            Line data    Source code
       1              : use std::fmt;
       2              : use std::num::ParseIntError;
       3              : use std::str::FromStr;
       4              : 
       5              : use anyhow::Context;
       6              : use hex::FromHex;
       7              : use rand::Rng;
       8              : use serde::de::Visitor;
       9              : use serde::{Deserialize, Serialize};
      10              : use thiserror::Error;
      11              : 
      12              : #[derive(Error, Debug)]
      13              : pub enum IdError {
      14              :     #[error("invalid id length {0}")]
      15              :     SliceParseError(usize),
      16              : }
      17              : 
      18              : /// Neon ID is a 128-bit random ID.
      19              : /// Used to represent various identifiers. Provides handy utility methods and impls.
      20              : ///
      21              : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
      22              : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
      23              : #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
      24              : struct Id([u8; 16]);
      25              : 
      26              : impl Serialize for Id {
      27         9623 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
      28         9623 :     where
      29         9623 :         S: serde::Serializer,
      30         9623 :     {
      31         9623 :         if serializer.is_human_readable() {
      32         2292 :             serializer.collect_str(self)
      33              :         } else {
      34         7331 :             self.0.serialize(serializer)
      35              :         }
      36         1039 :     }
      37              : }
      38              : 
      39              : impl<'de> Deserialize<'de> for Id {
      40         5377 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
      41         5377 :     where
      42         5377 :         D: serde::Deserializer<'de>,
      43         5377 :     {
      44              :         struct IdVisitor {
      45              :             is_human_readable_deserializer: bool,
      46              :         }
      47              : 
      48              :         impl<'de> Visitor<'de> for IdVisitor {
      49              :             type Value = Id;
      50              : 
      51            0 :             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
      52            0 :                 if self.is_human_readable_deserializer {
      53            0 :                     formatter.write_str("value in form of hex string")
      54              :                 } else {
      55            0 :                     formatter.write_str("value in form of integer array([u8; 16])")
      56              :                 }
      57            0 :             }
      58              : 
      59         4956 :             fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
      60         4956 :             where
      61         4956 :                 A: serde::de::SeqAccess<'de>,
      62         4956 :             {
      63         4956 :                 let s = serde::de::value::SeqAccessDeserializer::new(seq);
      64         4956 :                 let id: [u8; 16] = Deserialize::deserialize(s)?;
      65         4956 :                 Ok(Id::from(id))
      66            4 :             }
      67              : 
      68          421 :             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
      69          421 :             where
      70          421 :                 E: serde::de::Error,
      71          421 :             {
      72          421 :                 Id::from_str(v).map_err(E::custom)
      73          421 :             }
      74              :         }
      75              : 
      76         5377 :         if deserializer.is_human_readable() {
      77          421 :             deserializer.deserialize_str(IdVisitor {
      78          421 :                 is_human_readable_deserializer: true,
      79          421 :             })
      80              :         } else {
      81         4956 :             deserializer.deserialize_tuple(
      82         4956 :                 16,
      83         4956 :                 IdVisitor {
      84         4956 :                     is_human_readable_deserializer: false,
      85         4956 :                 },
      86         4956 :             )
      87              :         }
      88           51 :     }
      89              : }
      90              : 
      91              : impl Id {
      92           14 :     pub fn from_slice(src: &[u8]) -> Result<Id, IdError> {
      93           14 :         if src.len() != 16 {
      94            0 :             return Err(IdError::SliceParseError(src.len()));
      95           14 :         }
      96           14 :         let mut id_array = [0u8; 16];
      97           14 :         id_array.copy_from_slice(src);
      98           14 :         Ok(id_array.into())
      99           14 :     }
     100              : 
     101            9 :     pub fn as_arr(&self) -> [u8; 16] {
     102            9 :         self.0
     103            9 :     }
     104              : 
     105         7575 :     pub fn generate() -> Self {
     106         7575 :         let mut tli_buf = [0u8; 16];
     107         7575 :         rand::thread_rng().fill(&mut tli_buf);
     108         7575 :         Id::from(tli_buf)
     109         7575 :     }
     110              : 
     111       152112 :     fn hex_encode(&self) -> String {
     112              :         static HEX: &[u8] = b"0123456789abcdef";
     113              : 
     114       152112 :         let mut buf = vec![0u8; self.0.len() * 2];
     115      2433792 :         for (&b, chunk) in self.0.as_ref().iter().zip(buf.chunks_exact_mut(2)) {
     116      2433792 :             chunk[0] = HEX[((b >> 4) & 0xf) as usize];
     117      2433792 :             chunk[1] = HEX[(b & 0xf) as usize];
     118      2433792 :         }
     119              : 
     120              :         // SAFETY: vec constructed out of `HEX`, it can only be ascii
     121       152112 :         unsafe { String::from_utf8_unchecked(buf) }
     122       152112 :     }
     123              : }
     124              : 
     125              : impl FromStr for Id {
     126              :     type Err = hex::FromHexError;
     127              : 
     128        39343 :     fn from_str(s: &str) -> Result<Id, Self::Err> {
     129        39343 :         Self::from_hex(s)
     130        39343 :     }
     131              : }
     132              : 
     133              : // this is needed for pretty serialization and deserialization of Id's using serde integration with hex crate
     134              : impl FromHex for Id {
     135              :     type Error = hex::FromHexError;
     136              : 
     137        39357 :     fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
     138        39357 :         let mut buf: [u8; 16] = [0u8; 16];
     139        39357 :         hex::decode_to_slice(hex, &mut buf)?;
     140        39344 :         Ok(Id(buf))
     141        39357 :     }
     142              : }
     143              : 
     144              : impl AsRef<[u8]> for Id {
     145            0 :     fn as_ref(&self) -> &[u8] {
     146            0 :         &self.0
     147            0 :     }
     148              : }
     149              : 
     150              : impl From<[u8; 16]> for Id {
     151        79124 :     fn from(b: [u8; 16]) -> Self {
     152        79124 :         Id(b)
     153        79124 :     }
     154              : }
     155              : 
     156              : impl From<Id> for u128 {
     157            0 :     fn from(id: Id) -> Self {
     158            0 :         u128::from_le_bytes(id.0)
     159            0 :     }
     160              : }
     161              : 
     162              : impl fmt::Display for Id {
     163       128470 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     164       128470 :         f.write_str(&self.hex_encode())
     165       128470 :     }
     166              : }
     167              : 
     168              : impl fmt::Debug for Id {
     169        23642 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     170        23642 :         f.write_str(&self.hex_encode())
     171        23642 :     }
     172              : }
     173              : 
     174              : macro_rules! id_newtype {
     175              :     ($t:ident) => {
     176              :         impl $t {
     177           14 :             pub fn from_slice(src: &[u8]) -> Result<$t, IdError> {
     178           14 :                 Ok($t(Id::from_slice(src)?))
     179           14 :             }
     180              : 
     181            9 :             pub fn as_arr(&self) -> [u8; 16] {
     182            9 :                 self.0.as_arr()
     183            9 :             }
     184              : 
     185         7575 :             pub fn generate() -> Self {
     186         7575 :                 $t(Id::generate())
     187         7575 :             }
     188              : 
     189          124 :             pub const fn from_array(b: [u8; 16]) -> Self {
     190          124 :                 $t(Id(b))
     191          124 :             }
     192              :         }
     193              : 
     194              :         impl FromStr for $t {
     195              :             type Err = hex::FromHexError;
     196              : 
     197        38922 :             fn from_str(s: &str) -> Result<$t, Self::Err> {
     198        38922 :                 let value = Id::from_str(s)?;
     199        38909 :                 Ok($t(value))
     200        38922 :             }
     201              :         }
     202              : 
     203              :         impl From<[u8; 16]> for $t {
     204        66578 :             fn from(b: [u8; 16]) -> Self {
     205        66578 :                 $t(Id::from(b))
     206        66578 :             }
     207              :         }
     208              : 
     209              :         impl FromHex for $t {
     210              :             type Error = hex::FromHexError;
     211              : 
     212           14 :             fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
     213           14 :                 Ok($t(Id::from_hex(hex)?))
     214            6 :             }
     215              :         }
     216              : 
     217              :         impl AsRef<[u8]> for $t {
     218           50 :             fn as_ref(&self) -> &[u8] {
     219           50 :                 &self.0.0
     220           50 :             }
     221              :         }
     222              : 
     223              :         impl From<$t> for u128 {
     224            0 :             fn from(id: $t) -> Self {
     225            0 :                 u128::from(id.0)
     226            0 :             }
     227              :         }
     228              : 
     229              :         impl fmt::Display for $t {
     230       126178 :             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     231       126178 :                 self.0.fmt(f)
     232       126178 :             }
     233              :         }
     234              : 
     235              :         impl fmt::Debug for $t {
     236        23642 :             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     237        23642 :                 self.0.fmt(f)
     238        23642 :             }
     239              :         }
     240              :     };
     241              : }
     242              : 
     243              : /// Neon timeline ID.
     244              : ///
     245              : /// They are different from PostgreSQL timeline
     246              : /// IDs, but serve a similar purpose: they differentiate
     247              : /// between different "histories" of the same cluster.  However,
     248              : /// PostgreSQL timeline IDs are a bit cumbersome, because they are only
     249              : /// 32-bits wide, and they must be in ascending order in any given
     250              : /// timeline history.  Those limitations mean that we cannot generate a
     251              : /// new PostgreSQL timeline ID by just generating a random number. And
     252              : /// that in turn is problematic for the "pull/push" workflow, where you
     253              : /// have a local copy of a Neon repository, and you periodically sync
     254              : /// the local changes with a remote server. When you work "detached"
     255              : /// from the remote server, you cannot create a PostgreSQL timeline ID
     256              : /// that's guaranteed to be different from all existing timelines in
     257              : /// the remote server. For example, if two people are having a clone of
     258              : /// the repository on their laptops, and they both create a new branch
     259              : /// with different name. What timeline ID would they assign to their
     260              : /// branches? If they pick the same one, and later try to push the
     261              : /// branches to the same remote server, they will get mixed up.
     262              : ///
     263              : /// To avoid those issues, Neon has its own concept of timelines that
     264              : /// is separate from PostgreSQL timelines, and doesn't have those
     265              : /// limitations. A Neon timeline is identified by a 128-bit ID, which
     266              : /// is usually printed out as a hex string.
     267              : ///
     268              : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
     269              : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
     270              : /// See [`Id`] for alternative ways to serialize it.
     271            0 : #[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
     272              : pub struct TimelineId(Id);
     273              : 
     274              : id_newtype!(TimelineId);
     275              : 
     276              : impl TryFrom<Option<&str>> for TimelineId {
     277              :     type Error = anyhow::Error;
     278              : 
     279           16 :     fn try_from(value: Option<&str>) -> Result<Self, Self::Error> {
     280           16 :         value
     281           16 :             .unwrap_or_default()
     282           16 :             .parse::<TimelineId>()
     283           16 :             .with_context(|| format!("Could not parse timeline id from {:?}", value))
     284           16 :     }
     285              : }
     286              : 
     287              : /// Neon Tenant Id represents identifiar of a particular tenant.
     288              : /// Is used for distinguishing requests and data belonging to different users.
     289              : ///
     290              : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
     291              : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
     292              : /// See [`Id`] for alternative ways to serialize it.
     293            0 : #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
     294              : pub struct TenantId(Id);
     295              : 
     296              : id_newtype!(TenantId);
     297              : 
     298              : // A pair uniquely identifying Neon instance.
     299            0 : #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)]
     300              : pub struct TenantTimelineId {
     301              :     pub tenant_id: TenantId,
     302              :     pub timeline_id: TimelineId,
     303              : }
     304              : 
     305              : impl TenantTimelineId {
     306        44366 :     pub fn new(tenant_id: TenantId, timeline_id: TimelineId) -> Self {
     307        44366 :         TenantTimelineId {
     308        44366 :             tenant_id,
     309        44366 :             timeline_id,
     310        44366 :         }
     311        44366 :     }
     312              : 
     313          513 :     pub fn generate() -> Self {
     314          513 :         Self::new(TenantId::generate(), TimelineId::generate())
     315          513 :     }
     316              : 
     317        24528 :     pub fn empty() -> Self {
     318        24528 :         Self::new(TenantId::from([0u8; 16]), TimelineId::from([0u8; 16]))
     319        24528 :     }
     320              : }
     321              : 
     322              : impl fmt::Display for TenantTimelineId {
     323           51 :     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     324           51 :         write!(f, "{}/{}", self.tenant_id, self.timeline_id)
     325           51 :     }
     326              : }
     327              : 
     328              : impl FromStr for TenantTimelineId {
     329              :     type Err = anyhow::Error;
     330              : 
     331            0 :     fn from_str(s: &str) -> Result<Self, Self::Err> {
     332            0 :         let mut parts = s.split('/');
     333            0 :         let tenant_id = parts
     334            0 :             .next()
     335            0 :             .ok_or_else(|| anyhow::anyhow!("TenantTimelineId must contain tenant_id"))?
     336            0 :             .parse()?;
     337            0 :         let timeline_id = parts
     338            0 :             .next()
     339            0 :             .ok_or_else(|| anyhow::anyhow!("TenantTimelineId must contain timeline_id"))?
     340            0 :             .parse()?;
     341            0 :         if parts.next().is_some() {
     342            0 :             anyhow::bail!("TenantTimelineId must contain only tenant_id and timeline_id");
     343            0 :         }
     344            0 :         Ok(TenantTimelineId::new(tenant_id, timeline_id))
     345            0 :     }
     346              : }
     347              : 
     348              : // Unique ID of a storage node (safekeeper or pageserver). Supposed to be issued
     349              : // by the console.
     350            3 : #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
     351              : #[serde(transparent)]
     352              : pub struct NodeId(pub u64);
     353              : 
     354              : impl fmt::Display for NodeId {
     355          224 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     356          224 :         write!(f, "{}", self.0)
     357          224 :     }
     358              : }
     359              : 
     360              : impl FromStr for NodeId {
     361              :     type Err = ParseIntError;
     362            0 :     fn from_str(s: &str) -> Result<Self, Self::Err> {
     363            0 :         Ok(NodeId(u64::from_str(s)?))
     364            0 :     }
     365              : }
     366              : 
     367              : #[cfg(test)]
     368              : mod tests {
     369              :     use serde_assert::{Deserializer, Serializer, Token, Tokens};
     370              : 
     371              :     use super::*;
     372              :     use crate::bin_ser::BeSer;
     373              : 
     374              :     #[test]
     375            1 :     fn test_id_serde_non_human_readable() {
     376            1 :         let original_id = Id([
     377            1 :             173, 80, 132, 115, 129, 226, 72, 254, 170, 201, 135, 108, 199, 26, 228, 24,
     378            1 :         ]);
     379            1 :         let expected_tokens = Tokens(vec![
     380            1 :             Token::Tuple { len: 16 },
     381            1 :             Token::U8(173),
     382            1 :             Token::U8(80),
     383            1 :             Token::U8(132),
     384            1 :             Token::U8(115),
     385            1 :             Token::U8(129),
     386            1 :             Token::U8(226),
     387            1 :             Token::U8(72),
     388            1 :             Token::U8(254),
     389            1 :             Token::U8(170),
     390            1 :             Token::U8(201),
     391            1 :             Token::U8(135),
     392            1 :             Token::U8(108),
     393            1 :             Token::U8(199),
     394            1 :             Token::U8(26),
     395            1 :             Token::U8(228),
     396            1 :             Token::U8(24),
     397            1 :             Token::TupleEnd,
     398            1 :         ]);
     399            1 : 
     400            1 :         let serializer = Serializer::builder().is_human_readable(false).build();
     401            1 :         let serialized_tokens = original_id.serialize(&serializer).unwrap();
     402            1 :         assert_eq!(serialized_tokens, expected_tokens);
     403              : 
     404            1 :         let mut deserializer = Deserializer::builder()
     405            1 :             .is_human_readable(false)
     406            1 :             .tokens(serialized_tokens)
     407            1 :             .build();
     408            1 :         let deserialized_id = Id::deserialize(&mut deserializer).unwrap();
     409            1 :         assert_eq!(deserialized_id, original_id);
     410            1 :     }
     411              : 
     412              :     #[test]
     413            1 :     fn test_id_serde_human_readable() {
     414            1 :         let original_id = Id([
     415            1 :             173, 80, 132, 115, 129, 226, 72, 254, 170, 201, 135, 108, 199, 26, 228, 24,
     416            1 :         ]);
     417            1 :         let expected_tokens = Tokens(vec![Token::Str(String::from(
     418            1 :             "ad50847381e248feaac9876cc71ae418",
     419            1 :         ))]);
     420            1 : 
     421            1 :         let serializer = Serializer::builder().is_human_readable(true).build();
     422            1 :         let serialized_tokens = original_id.serialize(&serializer).unwrap();
     423            1 :         assert_eq!(serialized_tokens, expected_tokens);
     424              : 
     425            1 :         let mut deserializer = Deserializer::builder()
     426            1 :             .is_human_readable(true)
     427            1 :             .tokens(Tokens(vec![Token::Str(String::from(
     428            1 :                 "ad50847381e248feaac9876cc71ae418",
     429            1 :             ))]))
     430            1 :             .build();
     431            1 :         assert_eq!(Id::deserialize(&mut deserializer).unwrap(), original_id);
     432            1 :     }
     433              : 
     434              :     macro_rules! roundtrip_type {
     435              :         ($type:ty, $expected_bytes:expr) => {{
     436              :             let expected_bytes: [u8; 16] = $expected_bytes;
     437              :             let original_id = <$type>::from(expected_bytes);
     438              : 
     439              :             let ser_bytes = original_id.ser().unwrap();
     440              :             assert_eq!(ser_bytes, expected_bytes);
     441              : 
     442              :             let des_id = <$type>::des(&ser_bytes).unwrap();
     443              :             assert_eq!(des_id, original_id);
     444              :         }};
     445              :     }
     446              : 
     447              :     #[test]
     448            1 :     fn test_id_bincode_serde() {
     449            1 :         let expected_bytes = [
     450            1 :             173, 80, 132, 115, 129, 226, 72, 254, 170, 201, 135, 108, 199, 26, 228, 24,
     451            1 :         ];
     452            1 : 
     453            1 :         roundtrip_type!(Id, expected_bytes);
     454            1 :     }
     455              : 
     456              :     #[test]
     457            1 :     fn test_tenant_id_bincode_serde() {
     458            1 :         let expected_bytes = [
     459            1 :             173, 80, 132, 115, 129, 226, 72, 254, 170, 201, 135, 108, 199, 26, 228, 24,
     460            1 :         ];
     461            1 : 
     462            1 :         roundtrip_type!(TenantId, expected_bytes);
     463            1 :     }
     464              : 
     465              :     #[test]
     466            1 :     fn test_timeline_id_bincode_serde() {
     467            1 :         let expected_bytes = [
     468            1 :             173, 80, 132, 115, 129, 226, 72, 254, 170, 201, 135, 108, 199, 26, 228, 24,
     469            1 :         ];
     470            1 : 
     471            1 :         roundtrip_type!(TimelineId, expected_bytes);
     472            1 :     }
     473              : }
        

Generated by: LCOV version 2.1-beta