headless_lms_credit_registration/registry/
ids.rs1use std::borrow::Borrow;
4
5use secrecy::{ExposeSecret, SecretString};
6
7#[derive(Debug)]
9pub(crate) struct StudentNumber(SecretString);
10
11impl StudentNumber {
12 pub(crate) fn new(number: impl Into<SecretString>) -> Self {
13 Self(number.into())
14 }
15
16 pub(crate) fn as_secret(&self) -> &SecretString {
17 &self.0
18 }
19
20 pub(crate) fn expose(&self) -> &str {
21 self.0.expose_secret()
22 }
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
28pub(crate) struct CourseCode(String);
29
30impl CourseCode {
31 pub(crate) fn parse(code: &str) -> Option<Self> {
33 let code = code.trim();
34 (!code.is_empty()).then(|| Self(code.to_string()))
35 }
36
37 pub(crate) fn as_str(&self) -> &str {
38 &self.0
39 }
40}
41
42impl Borrow<str> for CourseCode {
43 fn borrow(&self) -> &str {
44 &self.0
45 }
46}
47
48#[derive(Debug, Clone, PartialEq, Eq)]
50pub(crate) struct AttainmentId(String);
51
52impl AttainmentId {
53 pub(crate) fn new(id: impl Into<String>) -> Self {
54 Self(id.into())
55 }
56
57 pub(crate) fn as_str(&self) -> &str {
58 &self.0
59 }
60}
61
62pub(crate) struct SubmittedAttainmentRef {
64 pub id: AttainmentId,
65 pub attainment_type: Option<String>,
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn a_course_code_is_trimmed_and_a_blank_one_is_none() {
74 assert_eq!(
75 CourseCode::parse(" TKT10002 ")
76 .as_ref()
77 .map(CourseCode::as_str),
78 Some("TKT10002")
79 );
80 assert_eq!(CourseCode::parse(" "), None);
81 }
82}