about summary refs log tree commit diff
path: root/src/atom/urn.rs
blob: 9ec73ae6ce24f0ead02a3b1282a3432fcdeda61b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
use core::fmt;

use rand::{rngs::OsRng, Rng};

//TODO: gen- Check URN are valid
// https://www.rfc-editor.org/rfc/rfc2141#section-2.1
pub struct Urn {
	/// Namespace Identifier
	nid: String,
	/// Namespace Specific string. This is the unique part of the identifier
	nss: String,
}

impl Urn {
	/// awake specific function for generating a URN in the form of:
	/// `urn:NID:1234-5678`
	/// Where 1234-5678 is a randomly generated eight digit ID broken in two.
	pub fn new_random<S: Into<String>>(nid: S) -> Self {
		let first = random_base58(4);
		let second = random_base58(4);

		Self {
			nid: nid.into(),
			nss: format!("{first}-{second}"),
		}
	}
}

impl fmt::Display for Urn {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		let Urn { nid, nss } = self;

		write!(f, "urn:{nid}:{nss}")
	}
}

const BASE58: &'static [u8] = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const USER_ID_LENGTH: usize = 6;
const SESSION_ID_LENGTH: usize = 12;

/// Random Base58 string, `count` characters long, using OsRng which is assumed
/// to be secure
/// > assumed that system always provides high-quality cryptographically secure random data
fn random_base58(count: usize) -> String {
	let mut rng = OsRng::default();
	std::iter::from_fn(|| Some(BASE58[rng.gen_range(0..BASE58.len())] as char))
		.take(count)
		.collect()
}