openpgp_card/ocard/data/
cardholder.rs1use std::convert::TryFrom;
7
8use crate::ocard::data::{CardholderRelatedData, Lang, Sex};
9use crate::ocard::tags::Tags;
10use crate::ocard::tlv::{value::Value, Tlv};
11
12impl CardholderRelatedData {
13 pub fn name(&self) -> Option<&[u8]> {
14 self.name.as_deref()
15 }
16
17 pub(crate) fn latin1_to_string(s: &[u8]) -> String {
22 s.iter().map(|&c| c as char).collect()
23 }
24
25 pub fn lang(&self) -> Option<&[Lang]> {
26 self.lang.as_deref()
27 }
28
29 pub fn sex(&self) -> Option<Sex> {
30 self.sex
31 }
32}
33
34impl TryFrom<&[u8]> for CardholderRelatedData {
35 type Error = crate::Error;
36
37 fn try_from(data: &[u8]) -> Result<Self, crate::Error> {
38 let value = Value::from(data, true)?;
39 let tlv = Tlv::new(Tags::CardholderRelatedData, value);
40
41 let name: Option<Vec<u8>> = tlv.find(Tags::Name).map(|v| v.serialize().to_vec());
42
43 let lang: Option<Vec<Lang>> = tlv.find(Tags::LanguagePref).map(|v| {
44 v.serialize()
45 .chunks(2)
46 .map(|c| match c.len() {
47 2 => Lang::from(&[c[0], c[1]]),
48 1 => Lang::from(&[c[0]]),
49 _ => unreachable!(),
50 })
51 .collect()
52 });
53
54 let sex = tlv
55 .find(Tags::Sex)
56 .map(|v| v.serialize())
57 .filter(|v| v.len() == 1)
58 .map(|v| Sex::from(v[0]));
59
60 Ok(CardholderRelatedData { name, lang, sex })
61 }
62}
63
64#[cfg(test)]
65mod test {
66 use super::*;
67
68 #[test]
69 fn test() {
70 let data = [
71 0x5b, 0x8, 0x42, 0x61, 0x72, 0x3c, 0x3c, 0x46, 0x6f, 0x6f, 0x5f, 0x2d, 0x4, 0x64, 0x65,
72 0x65, 0x6e, 0x5f, 0x35, 0x1, 0x32,
73 ];
74
75 let ch = CardholderRelatedData::try_from(&data[..]).expect("failed to parse cardholder");
76
77 assert_eq!(
78 ch,
79 CardholderRelatedData {
80 name: Some("Bar<<Foo".as_bytes().to_vec()),
81 lang: Some(vec![['d', 'e'].into(), ['e', 'n'].into()]),
82 sex: Some(Sex::Female)
83 }
84 );
85 }
86}