More explicit data type Lang
for language.
This commit is contained in:
parent
889eedbb79
commit
dcf73bd86d
7 changed files with 70 additions and 24 deletions
|
@ -334,7 +334,7 @@ pub fn test_set_user_data(
|
|||
card_client.set_name(b"Bar<<Foo")?;
|
||||
|
||||
// lang
|
||||
card_client.set_lang(b"deen")?;
|
||||
card_client.set_lang(&[['d', 'e'].into(), ['e', 'n'].into()])?;
|
||||
|
||||
// sex
|
||||
card_client.set_sex(Sex::Female)?;
|
||||
|
@ -348,7 +348,7 @@ pub fn test_set_user_data(
|
|||
assert_eq!(ch.name().as_deref(), Some("Bar<<Foo".as_bytes()));
|
||||
assert_eq!(
|
||||
ch.lang().expect("Language setting is None"),
|
||||
&[[b'd', b'e'], [b'e', b'n']]
|
||||
&[['d', 'e'].into(), ['e', 'n'].into()]
|
||||
);
|
||||
assert_eq!(ch.sex(), Some(Sex::Female));
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ use openpgp_card::algorithm::{Algo, AlgoInfo, AlgoSimple};
|
|||
use openpgp_card::card_do::{
|
||||
ApplicationIdentifier, ApplicationRelatedData, CardholderRelatedData,
|
||||
ExtendedCapabilities, ExtendedLengthInfo, Fingerprint, HistoricalBytes,
|
||||
KeyGenerationTime, PWStatusBytes, SecuritySupportTemplate, Sex,
|
||||
KeyGenerationTime, Lang, PWStatusBytes, SecuritySupportTemplate, Sex,
|
||||
};
|
||||
use openpgp_card::{CardClient, Error, KeySet, KeyType, Response};
|
||||
|
||||
|
@ -411,12 +411,12 @@ impl Admin<'_, '_> {
|
|||
self.oc.card_client.set_name(name.as_bytes())
|
||||
}
|
||||
|
||||
pub fn set_lang(&mut self, lang: &str) -> Result<Response, Error> {
|
||||
pub fn set_lang(&mut self, lang: &[Lang]) -> Result<Response, Error> {
|
||||
if lang.len() > 8 {
|
||||
return Err(anyhow!("lang too long").into());
|
||||
}
|
||||
|
||||
self.oc.card_client.set_lang(lang.as_bytes())
|
||||
self.oc.card_client.set_lang(lang)
|
||||
}
|
||||
|
||||
pub fn set_sex(&mut self, sex: Sex) -> Result<Response, Error> {
|
||||
|
|
|
@ -111,7 +111,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
let res = admin.set_sex(Sex::NotApplicable)?;
|
||||
println!("set sex {:x?}", res);
|
||||
|
||||
let res = admin.set_lang("en")?;
|
||||
let res = admin.set_lang(&[['e', 'n'].into()])?;
|
||||
println!("set lang {:x?}", res);
|
||||
|
||||
let res = admin.set_url("https://keys.openpgp.org")?;
|
||||
|
|
|
@ -285,7 +285,7 @@ pub struct ExtendedLengthInfo {
|
|||
#[derive(Debug, PartialEq)]
|
||||
pub struct CardholderRelatedData {
|
||||
name: Option<Vec<u8>>,
|
||||
lang: Option<Vec<[u8; 2]>>,
|
||||
lang: Option<Vec<Lang>>,
|
||||
sex: Option<Sex>,
|
||||
}
|
||||
|
||||
|
@ -298,6 +298,45 @@ pub enum Sex {
|
|||
NotApplicable,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum Lang {
|
||||
Value([u8; 2]),
|
||||
Invalid(u8),
|
||||
}
|
||||
|
||||
impl From<(char, char)> for Lang {
|
||||
fn from(c: (char, char)) -> Self {
|
||||
Lang::Value([c.0 as u8, c.1 as u8])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[char; 2]> for Lang {
|
||||
fn from(c: [char; 2]) -> Self {
|
||||
Lang::Value([c[0] as u8, c[1] as u8])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Lang> for Vec<u8> {
|
||||
fn from(lang: Lang) -> Self {
|
||||
match lang {
|
||||
Lang::Value(v) => vec![v[0], v[1]],
|
||||
Lang::Invalid(v) => vec![v],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8; 1]> for Lang {
|
||||
fn from(data: &[u8; 1]) -> Self {
|
||||
Lang::Invalid(data[0])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8; 2]> for Lang {
|
||||
fn from(data: &[u8; 2]) -> Self {
|
||||
Lang::Value([data[0], data[1]])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Sex> for u8 {
|
||||
fn from(sex: &Sex) -> u8 {
|
||||
match sex {
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::convert::TryFrom;
|
|||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::card_do::{CardholderRelatedData, Sex};
|
||||
use crate::card_do::{CardholderRelatedData, Lang, Sex};
|
||||
use crate::tlv::{value::Value, Tlv};
|
||||
|
||||
impl CardholderRelatedData {
|
||||
|
@ -15,7 +15,7 @@ impl CardholderRelatedData {
|
|||
self.name.as_deref()
|
||||
}
|
||||
|
||||
pub fn lang(&self) -> Option<&[[u8; 2]]> {
|
||||
pub fn lang(&self) -> Option<&[Lang]> {
|
||||
self.lang.as_deref()
|
||||
}
|
||||
|
||||
|
@ -34,9 +34,17 @@ impl TryFrom<&[u8]> for CardholderRelatedData {
|
|||
let name: Option<Vec<u8>> =
|
||||
tlv.find(&[0x5b].into()).map(|v| v.serialize().to_vec());
|
||||
|
||||
let lang: Option<Vec<[u8; 2]>> = tlv
|
||||
.find(&[0x5f, 0x2d].into())
|
||||
.map(|v| v.serialize().chunks(2).map(|c| [c[0], c[1]]).collect());
|
||||
let lang: Option<Vec<Lang>> =
|
||||
tlv.find(&[0x5f, 0x2d].into()).map(|v| {
|
||||
v.serialize()
|
||||
.chunks(2)
|
||||
.map(|c| match c.len() {
|
||||
2 => Lang::from(&[c[0], c[1]]),
|
||||
1 => Lang::from(&[c[0]]),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
|
||||
let sex = tlv
|
||||
.find(&[0x5f, 0x35].into())
|
||||
|
@ -66,7 +74,7 @@ mod test {
|
|||
ch,
|
||||
CardholderRelatedData {
|
||||
name: Some("Bar<<Foo".as_bytes().to_vec()),
|
||||
lang: Some(vec![[b'd', b'e'], [b'e', b'n']]),
|
||||
lang: Some(vec![['d', 'e'].into(), ['e', 'n'].into()]),
|
||||
sex: Some(Sex::Female)
|
||||
}
|
||||
);
|
||||
|
|
|
@ -48,7 +48,7 @@ use crate::apdu::commands;
|
|||
use crate::apdu::response::RawResponse;
|
||||
use crate::card_do::{
|
||||
ApplicationRelatedData, CardholderRelatedData, Fingerprint,
|
||||
KeyGenerationTime, PWStatusBytes, SecuritySupportTemplate, Sex,
|
||||
KeyGenerationTime, Lang, PWStatusBytes, SecuritySupportTemplate, Sex,
|
||||
};
|
||||
use crate::crypto_data::{
|
||||
CardUploadableKey, Cryptogram, Hash, PublicKeyMaterial,
|
||||
|
@ -755,8 +755,14 @@ impl<'a> dyn CardClient + 'a {
|
|||
apdu::send_command(self, put_name, false)?.try_into()
|
||||
}
|
||||
|
||||
pub fn set_lang(&mut self, lang: &[u8]) -> Result<Response, Error> {
|
||||
let put_lang = commands::put_lang(lang.to_vec());
|
||||
pub fn set_lang(&mut self, lang: &[Lang]) -> Result<Response, Error> {
|
||||
let bytes: Vec<u8> = lang
|
||||
.iter()
|
||||
.map(|&l| Into::<Vec<u8>>::into(l))
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
let put_lang = commands::put_lang(bytes);
|
||||
apdu::send_command(self, put_lang, false)?.try_into()
|
||||
}
|
||||
|
||||
|
|
|
@ -215,14 +215,7 @@ fn print_status(ident: Option<String>, verbose: bool) -> Result<()> {
|
|||
}
|
||||
|
||||
if let Some(lang) = crd.lang() {
|
||||
let lang = lang
|
||||
.iter()
|
||||
.map(|lang| {
|
||||
lang.iter().map(|&u| char::from(u)).collect::<String>()
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
println!("Language preferences '{}'", lang);
|
||||
println!("Language preferences '{:?}'", lang);
|
||||
}
|
||||
|
||||
// information about subkeys
|
||||
|
|
Loading…
Reference in a new issue