feat: raw (non-deserialized) implementation of the 01 group of LireCartePS
This commit is contained in:
parent
4e3387cef9
commit
cb4d352f12
@ -54,6 +54,8 @@ pub struct GroupId(
|
||||
#[deku(ctx = "group_id: u16", id = "group_id")]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum DataGroup {
|
||||
#[deku(id = 1)]
|
||||
LireCartePS_Group1_Holder(groups::ssv_lire_carte_ps::group_1_holder::Holder),
|
||||
#[deku(id = 60)]
|
||||
LireConfig_Group60_ConfigHeader(groups::ssv_lire_config::group_60_header_config::ConfigHeader),
|
||||
#[deku(id = 61)]
|
||||
|
@ -4,6 +4,7 @@ use deku::{deku_derive, DekuError};
|
||||
|
||||
use super::{ size_read, map_bytes_to_lossy_string };
|
||||
|
||||
pub mod ssv_lire_carte_ps;
|
||||
pub mod ssv_lire_config;
|
||||
|
||||
/// # Convert a DataField to a specific type
|
||||
@ -43,6 +44,11 @@ pub struct NumericString(
|
||||
#[deku(map = "map_from_data_field")]
|
||||
String
|
||||
);
|
||||
impl From<&str> for NumericString {
|
||||
fn from(s: &str) -> Self {
|
||||
NumericString(s.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[deku_derive(DekuRead)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
145
crates/fsv/src/fsv_parsing/groups/ssv_lire_carte_ps.rs
Normal file
145
crates/fsv/src/fsv_parsing/groups/ssv_lire_carte_ps.rs
Normal file
@ -0,0 +1,145 @@
|
||||
//! # Structures de parsing des données de la fonction SSV_LireCartePS
|
||||
|
||||
use deku::deku_derive;
|
||||
|
||||
use crate::fsv_parsing::groups::NumericString;
|
||||
|
||||
/// # Titulaire
|
||||
/// 1 occurence
|
||||
pub mod group_1_holder {
|
||||
|
||||
use crate::fsv_parsing::groups::AlphaNumericString;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Groupe 1 - Titulaire
|
||||
#[deku_derive(DekuRead)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Holder {
|
||||
pub card_type: CardPSType,
|
||||
pub national_id_type: NationalIDType,
|
||||
pub national_id: AlphaNumericString, // /!\ CE and not CA
|
||||
pub national_id_key: AlphaNumericString,
|
||||
pub civility_code: CivilityCode,
|
||||
pub holder_lastname: AlphaNumericString, // /!\ CE and not CA
|
||||
pub holder_firstname: AlphaNumericString, // /!\ CE and not CA
|
||||
pub category_card: AlphaNumericString,
|
||||
}
|
||||
|
||||
// Fields
|
||||
#[deku_derive(DekuRead)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct CardPSType(pub NumericString);
|
||||
|
||||
#[deku_derive(DekuRead)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct NationalIDType(pub NumericString);
|
||||
|
||||
#[deku_derive(DekuRead)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct CivilityCode(pub NumericString);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use deku::DekuContainerRead as _;
|
||||
|
||||
use crate::fsv_parsing::blocks::BlockHeader;
|
||||
|
||||
use super::*;
|
||||
|
||||
mod data {
|
||||
pub const BUFFER: &[u8] = &[
|
||||
0, 1, // Block ID
|
||||
53, // Block size
|
||||
1, // Type de carte PS, 2 CN
|
||||
48, // 0
|
||||
1, // Type d'identification nationale, 1 CN
|
||||
56, // 8
|
||||
11, // N° d'identification nationale, 8-30 CE
|
||||
57, 57, 55, 48, 48, 53, 57, 51, 54, 56, 54,
|
||||
1, // Clé du N° d'identification nationale, 1 CN
|
||||
54, // 6
|
||||
2, // Code civilité, 2 CN
|
||||
51, 49, // 31
|
||||
23, // Nom du PS, 27 CE
|
||||
80, 72, 65, 82, 77, 79, 70, 70, 73, 67,
|
||||
69, 32, 82, 80, 80, 83, 48, 48, 53, 57,
|
||||
51, 54, 56,
|
||||
7, // Prénom du PS, 27 CE
|
||||
71, 73, 76, 66, 69, 82, 84,
|
||||
// ??? Missing ??? Catégorie Carte, 1 CA
|
||||
0, 2, // Block ID
|
||||
93, // Block size
|
||||
1, // N° logique de la situation de facturation du PS, 1 CB
|
||||
1,
|
||||
1, // Mode d'exercice, 2 CN
|
||||
48,
|
||||
1, // Statut d'exercice, 3 CN
|
||||
49,
|
||||
2, // Secteur d'activité, 3 CN
|
||||
56, 54,
|
||||
1, // Type d'identification structure, 1 CN
|
||||
49,
|
||||
9, // N° d'identification structure, 14 CA
|
||||
48, 66, 48, 50, 52, 54, 50, 56, 54,
|
||||
1, // Clé du N° d'identification structure, 1 CN
|
||||
54,
|
||||
34, // Raison sociale structure, 40 CE
|
||||
80, 72, 65, 82, 77, 65, 67, 73, 69, 32,
|
||||
68, 69, 32, 76, 65, 32, 71, 65, 82, 69,
|
||||
32, 82, 79, 85, 84, 73, 69, 82, 69, 50,
|
||||
52, 54, 50, 56,
|
||||
8, // N° d'identification de facturation du PS, 8 CN
|
||||
48, 48, 50, 48, 57, 51, 54, 56,
|
||||
1, // Clé du N° d'identification de facturation du PS, 1 CN
|
||||
48,
|
||||
0, // N° d'identification du PS remplaçant, 30 CA
|
||||
1, // Clé du N° d'identification du PS remplaçant, 1 CN
|
||||
48,
|
||||
1, // Code conventionnel, 1 CN
|
||||
49,
|
||||
2, // Code spécialité, 2 CN
|
||||
53, 48,
|
||||
2, // Code zone tarifaire, 2 CN
|
||||
49, 48,
|
||||
2, // Code zone IK
|
||||
48, 48,
|
||||
1, // Code agrément 1, 1 CN
|
||||
48,
|
||||
1, // Code agrément 2, 1 CN
|
||||
48,
|
||||
1, // Code agrément 3, 1 CN
|
||||
48,
|
||||
1, // Habilitation à signer une Facture // 1 CN
|
||||
49,
|
||||
1, // Habilitation à signer un lot // 1 CN
|
||||
49
|
||||
];
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lire_carte_ps_first_header() {
|
||||
// env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging
|
||||
let ((_rest, _offset), block_header) = BlockHeader::from_bytes((data::BUFFER, 0)).unwrap();
|
||||
assert_eq!(block_header.group_id.0, 1, "Header ID");
|
||||
assert_eq!(block_header.data_size, 53, "Header Size");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_group_1_holder() {
|
||||
env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging
|
||||
let offset = 3*8;
|
||||
let (_rest, holder) = group_1_holder::Holder::from_bytes((data::BUFFER, offset)).unwrap();
|
||||
assert_eq!(holder.card_type.0.0, "0", "Card type");
|
||||
assert_eq!(holder.national_id_type.0.0, "8", "National ID type");
|
||||
assert_eq!(holder.national_id.0, "99700593686", "National Id");
|
||||
assert_eq!(holder.national_id_key.0, "6", "National ID Key");
|
||||
assert_eq!(holder.civility_code.0.0, "31", "Civility Code");
|
||||
assert_eq!(holder.holder_lastname.0, "PHARMOFFICE RPPS0059368", "Holder Lastname");
|
||||
assert_eq!(holder.holder_firstname.0, "GILBERT", "Holder Firstname");
|
||||
assert!(holder.category_card.0.is_empty(), "Category card");
|
||||
}
|
||||
}
|
@ -209,7 +209,7 @@ mod tests {
|
||||
|
||||
let ((_rest, _offset), block_header) = BlockHeader::from_bytes((buffer, offset)).unwrap();
|
||||
assert_eq!(block_header.group_id.0, 60, "Header ID");
|
||||
// assert_eq!(block_header.data_size, 15, "Header Size");
|
||||
assert_eq!(block_header.data_size, 15, "Header Size");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -289,6 +289,7 @@ mod tests {
|
||||
assert_eq!(content.name.0.0, "Gemalto PC Twin Reader (645D94C3) 00 00", "Reader Name");
|
||||
assert_eq!(content.card_type.0.0, "2", "Card Type");
|
||||
},
|
||||
_ => panic!("Unexpected data block type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ impl SSV {
|
||||
|
||||
/// # Read the CPS card
|
||||
/// Implement: SSV_LireCartePS
|
||||
pub fn read_professional_card(&self, pin_code: &str) -> Result<(), Error> {
|
||||
pub fn read_professional_card(&self, pin_code: &str) -> Result<Data, Error> {
|
||||
let pcsc_reader_name = "Gemalto PC Twin Reader (645D94C3) 00 00";
|
||||
|
||||
let pin_code = CString::new(pin_code).expect("CString::new failed");
|
||||
@ -111,12 +111,13 @@ impl SSV {
|
||||
let error = SSVErrorCodes::from(result);
|
||||
return Err(Error::SSVError(error));
|
||||
}
|
||||
// Print 10 bytes of the buffer
|
||||
let buffer = unsafe { std::slice::from_raw_parts(out_buffer_ptr as *const u8, 10) };
|
||||
println!("{:?}", buffer);
|
||||
// Parse the buffer into a Data struct
|
||||
let buffer = unsafe { std::slice::from_raw_parts(out_buffer_ptr as *const u8, out_buffer_size) };
|
||||
let (_rest, cps_blocks) = Data::from_bytes((buffer, 0)).unwrap();
|
||||
|
||||
// Free memory
|
||||
unsafe { libc::free(out_buffer_ptr) };
|
||||
Ok(())
|
||||
Ok(cps_blocks)
|
||||
}
|
||||
|
||||
/// # Get the configuration of the SSV library
|
||||
|
Loading…
Reference in New Issue
Block a user