feat: add first draft for crate public api
This commit is contained in:
parent
9539eeb6d0
commit
057f2aaaec
@ -1,122 +1,46 @@
|
|||||||
// to include std in docs, need to remove later
|
|
||||||
#[doc(inline)]
|
|
||||||
pub use std;
|
|
||||||
|
|
||||||
mod bindings;
|
mod bindings;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
use std::io::Cursor;
|
|
||||||
|
|
||||||
use bindings::SSV_LireConfig;
|
use bindings::SSV_LireConfig;
|
||||||
use binrw::BinRead;
|
use std::{fmt, ptr};
|
||||||
use std::ptr;
|
use types::serialization_types::{read_from_buffer, Configuration};
|
||||||
use types::serialization_types::{DataBlock, DataField};
|
|
||||||
|
|
||||||
//pub fn read_carte_professionnel_sante() -> Result<CarteProfessionnelSante, _> {
|
#[derive(Debug)]
|
||||||
// // how to init buffer and give it to library
|
pub struct SesamVitaleError {
|
||||||
// // https://stackoverflow.com/questions/58231215/what-is-proper-rust-way-to-allocate-opaque-buffer-for-external-c-library
|
code: u16,
|
||||||
// //
|
|
||||||
// // when init memory zones and they are too large to be a single memory zone -> https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0c1f0fca7d98a97bbc70dba786bbedd9
|
|
||||||
// unsafe {
|
|
||||||
// let nom_ressource_ps;
|
|
||||||
// let nom_ressource_lecteur;
|
|
||||||
// let code_porteur_ps;
|
|
||||||
// let p_zdata_out;
|
|
||||||
// let p_taille_zone;
|
|
||||||
// let status_code: u16 = SSV_LireCartePS(
|
|
||||||
// nom_ressource_ps,
|
|
||||||
// nom_ressource_lecteur,
|
|
||||||
// code_porteur_ps,
|
|
||||||
// p_zdata_out,
|
|
||||||
// p_taille_zone,
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// if status_code != 0 {
|
|
||||||
// return Err(());
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//}
|
|
||||||
|
|
||||||
// To parse the data
|
|
||||||
// allocate the multiple buffers
|
|
||||||
// chain them to make a single buffer
|
|
||||||
// use the parse_data_size function to get a size
|
|
||||||
// use take method to limit number of bytes read
|
|
||||||
// use binread implementaiton on each struct/enum de structure it
|
|
||||||
// do this recursively until there is no more data
|
|
||||||
|
|
||||||
// Memory has three embricked concepts:
|
|
||||||
// Memory Zone(s) -Contains-> DataBlock(s) -Contains-> DataField(s)
|
|
||||||
// DataBlocks (and DataFields) can be cut off by the end of a memory zone
|
|
||||||
// the data continues on the following memory zone
|
|
||||||
//#[binread]
|
|
||||||
pub struct DataBlock2 {
|
|
||||||
//<T> {
|
|
||||||
data_struct_id: u16,
|
|
||||||
|
|
||||||
// #[br(temp, parse_with = parse_data_size)]
|
|
||||||
memory_size: u32,
|
|
||||||
// spec indicates the DataBlock can be very large (up to 4GB)
|
|
||||||
// in this case, we can use memmap2 to use the disk to store the data
|
|
||||||
// pub data: Vec<DataField<T>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SSVError {
|
impl fmt::Display for SesamVitaleError {
|
||||||
Error(u16),
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
}
|
write!(f, "Got error code {} from SSV_LireConfig", self.code)
|
||||||
|
|
||||||
struct Parseable<T: BinRead>(T);
|
|
||||||
|
|
||||||
impl<T> BinRead for Parseable<T>
|
|
||||||
where
|
|
||||||
for<'a> T: BinRead<Args<'a> = ()>,
|
|
||||||
{
|
|
||||||
type Args<'a> = <DataField<T> as BinRead>::Args<'a>;
|
|
||||||
|
|
||||||
fn read_options<R: std::io::prelude::Read + std::io::prelude::Seek>(
|
|
||||||
reader: &mut R,
|
|
||||||
endian: binrw::Endian,
|
|
||||||
args: Self::Args<'_>,
|
|
||||||
) -> binrw::prelude::BinResult<Self> {
|
|
||||||
let field = DataField::<T>::read_options(reader, endian, args)?;
|
|
||||||
Ok(Parseable(field.value))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(BinRead)]
|
|
||||||
struct ConfigHeader {
|
|
||||||
ssv_version: Parseable<u16>,
|
|
||||||
galss_version: Parseable<u16>,
|
|
||||||
pss_version: Parseable<u16>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(BinRead)]
|
pub fn read_config() -> Result<Configuration, SesamVitaleError> {
|
||||||
struct ReaderConfig {
|
|
||||||
// manufacturer_name: Parseable<String>
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_config() -> Result<(), SSVError> {
|
|
||||||
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
|
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
|
||||||
let mut size: libc::size_t = 0;
|
let mut size: libc::size_t = 0;
|
||||||
|
|
||||||
let buffer: &[u8] = unsafe {
|
let buffer_ptr_ptr: *mut *mut libc::c_void = &mut buffer_ptr;
|
||||||
match SSV_LireConfig(&mut buffer_ptr, &mut size) {
|
let size_ptr: *mut libc::size_t = &mut size;
|
||||||
0 => (),
|
|
||||||
error_code => return Err(SSVError::Error(error_code)),
|
|
||||||
}
|
|
||||||
|
|
||||||
std::slice::from_raw_parts(buffer_ptr as *const u8, size)
|
// Need to add proper error handling -> return a result with error code pointing to an error
|
||||||
|
// enum
|
||||||
|
let exit_code: u16 = unsafe { SSV_LireConfig(buffer_ptr_ptr, size_ptr) };
|
||||||
|
|
||||||
|
if exit_code != 0 {
|
||||||
|
let error = SesamVitaleError { code: exit_code };
|
||||||
|
return Err(error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let buffer: &[u8] = unsafe { std::slice::from_raw_parts(buffer_ptr as *const u8, size) };
|
||||||
|
|
||||||
|
// TODO: Improve error handling
|
||||||
|
let configuration: Configuration = read_from_buffer(buffer).unwrap();
|
||||||
|
|
||||||
|
// TODO: Call library function for memory delocating
|
||||||
unsafe { libc::free(buffer_ptr) };
|
unsafe { libc::free(buffer_ptr) };
|
||||||
|
|
||||||
println!("Buffer data: {:?}", buffer);
|
Ok(configuration)
|
||||||
|
|
||||||
let cursor = &mut Cursor::new(buffer);
|
|
||||||
while size > 0 {
|
|
||||||
let data_block = DataBlock::read(cursor).expect("");
|
|
||||||
size -= data_block.data.len();
|
|
||||||
println!("{}", String::from_utf8(data_block.data).expect(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,176 +0,0 @@
|
|||||||
struct Identification<T> {
|
|
||||||
value: T,
|
|
||||||
// Key to check the validity of the value
|
|
||||||
// TODO: implement checking algorithm
|
|
||||||
key: u8,
|
|
||||||
}
|
|
||||||
type Byte = u8;
|
|
||||||
|
|
||||||
enum IdentificationNationale {
|
|
||||||
NumeroAdeli(String),
|
|
||||||
NumeroEmployeeDansStructure(IdentificationStructure, String),
|
|
||||||
NumeroDRASS(String),
|
|
||||||
NumeroRPPS(String),
|
|
||||||
/// N° Etudiant Médecin type ADELI sur 9 caractères (information transmise par l’ANS)
|
|
||||||
NumeroEtudiantMedecin(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TypeCarteProfessionnelSante {
|
|
||||||
/// Carte de Professionnel de Santé (CPS)
|
|
||||||
CarteDeProfessionnelSante,
|
|
||||||
/// Carte de Professionnel de Santé en Formation (CPF)
|
|
||||||
CarteDeProfessionnelSanteEnFormation,
|
|
||||||
/// Carte de Personnel d'Établissement de Santé (CDE/CPE)
|
|
||||||
CarteDePersonnelEtablissementSante,
|
|
||||||
/// Carte de Personnel Autorisé (CDA/CPA)
|
|
||||||
CarteDePersonnelAutorise,
|
|
||||||
/// Carte de Personne Morale
|
|
||||||
CarteDePersonneMorale,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CategorieCarteProfessionnelSante {
|
|
||||||
Reelle,
|
|
||||||
Test,
|
|
||||||
Demonstration,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CodeCivilite {
|
|
||||||
Adjudant,
|
|
||||||
Amiral,
|
|
||||||
Aspirant,
|
|
||||||
Aumônier,
|
|
||||||
Capitaine,
|
|
||||||
Cardinal,
|
|
||||||
Chanoine,
|
|
||||||
Colonel,
|
|
||||||
Commandant,
|
|
||||||
Commissaire,
|
|
||||||
Conseiller,
|
|
||||||
Directeur,
|
|
||||||
Docteur,
|
|
||||||
Douanier,
|
|
||||||
Epouxse, // Epoux(se)
|
|
||||||
Evêque,
|
|
||||||
Général,
|
|
||||||
Gouverneur,
|
|
||||||
Ingénieur,
|
|
||||||
Inspecteur,
|
|
||||||
Lieutenant,
|
|
||||||
Madame,
|
|
||||||
Mademoiselle,
|
|
||||||
Maître,
|
|
||||||
Maréchal,
|
|
||||||
Médecin,
|
|
||||||
Mesdames,
|
|
||||||
Mesdemoiselles,
|
|
||||||
Messieurs,
|
|
||||||
Monseigneur,
|
|
||||||
Monsieur,
|
|
||||||
NotreDame,
|
|
||||||
Pasteur,
|
|
||||||
Préfet,
|
|
||||||
Président,
|
|
||||||
Professeur,
|
|
||||||
Recteur,
|
|
||||||
Sergent,
|
|
||||||
SousPréfet,
|
|
||||||
Technicien,
|
|
||||||
Veuve,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CarteProfessionnelSante {
|
|
||||||
type_carte: TypeCarteProfessionnelSante,
|
|
||||||
categorie_carte: CategorieCarteProfessionnelSante,
|
|
||||||
professionnel_sante: ProfessionnelDeSante,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ProfessionnelDeSante {
|
|
||||||
prenom: String,
|
|
||||||
nom: String,
|
|
||||||
code_civilite: CodeCivilite,
|
|
||||||
identification_nationale: Identification<IdentificationNationale>,
|
|
||||||
situations_execice: Vec<SituationDExercice>,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum IdentificationStructure {
|
|
||||||
NumeroAdeliCabinet(String),
|
|
||||||
NumeroFINESS(String),
|
|
||||||
NumeroSIREN(String),
|
|
||||||
NumeroSIRET(String),
|
|
||||||
NumeroRPPSCabinet(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
struct StructureMedicale {
|
|
||||||
identification: Identification<IdentificationStructure>,
|
|
||||||
raison_sociale: String, // Nom Entreprise
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ModeExercice {
|
|
||||||
LiberalExploitantCommercant, // Libéral, exploitant, commerçant
|
|
||||||
Salarie,
|
|
||||||
Remplacant,
|
|
||||||
Benevole,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum StatutExercice {
|
|
||||||
// TAB-Statuts géré par l’ANS il faut trouver la donnee
|
|
||||||
PLACEHOLDER(u8),
|
|
||||||
}
|
|
||||||
|
|
||||||
enum SecteurActivite {
|
|
||||||
EtablissementPublicDeSanté,
|
|
||||||
HopitauxMilitaires,
|
|
||||||
EtablissementPrivePSPH, // Participant au Service Public Hospitalier
|
|
||||||
EtablissementPriveNonPSPH,
|
|
||||||
DispensaireDeSoins,
|
|
||||||
AutresStructuresDeSoinsRelevantDuServiceDeSanteDesArmees,
|
|
||||||
CabinetIndividuel,
|
|
||||||
CabinetDeGroupe,
|
|
||||||
ExerciceEnSociete,
|
|
||||||
SecteurPrivePHTempsPlein,
|
|
||||||
TransportSanitaire,
|
|
||||||
EntrepriseDInterim,
|
|
||||||
EtablissementDeSoinsEtPrevention,
|
|
||||||
PreventionEtSoinsEnEntreprise,
|
|
||||||
SanteScolaireEtUniversitaire,
|
|
||||||
RecrutementEtGestionRH,
|
|
||||||
PMIPlanificationFamiliale,
|
|
||||||
EtablissementPourHandicapes,
|
|
||||||
ComMarketingConsultingMedia,
|
|
||||||
EtablissementPersonnesAgees,
|
|
||||||
EtablissementAideaLaFamille,
|
|
||||||
EtablissementDEnseignement,
|
|
||||||
EtablissementsDeProtectionDeLEnfance,
|
|
||||||
EtablissementsDHebergementEtDeReadaptation,
|
|
||||||
Recherche,
|
|
||||||
AssurancePrivee,
|
|
||||||
OrganismeDeSecuriteSociale,
|
|
||||||
MinistèreEtServicesDeconcentres,
|
|
||||||
CollectivitesTerritoriales,
|
|
||||||
AssociationsEtOrganitationsHumanitaire,
|
|
||||||
LaboratoireDeBiologieMedicale,
|
|
||||||
AutreEtablissementSanitaire,
|
|
||||||
ProductionCommercialisationGrosBienMedicaux,
|
|
||||||
CommerceDétailDeBiensMédicaux,
|
|
||||||
PharmacieDOfficine,
|
|
||||||
CentreDeDialyse,
|
|
||||||
ParaPharmacie,
|
|
||||||
AutreSecteurDActivité,
|
|
||||||
SecteurNonDefini,
|
|
||||||
CentreAntiCancer,
|
|
||||||
CentreDeTransfusionSanguine,
|
|
||||||
RépartitionDistribributionFabricationExploitationImportationMedicamentsEtDispositifsMédicaux,
|
|
||||||
IncendiesEtSecours,
|
|
||||||
EntreprisesIndustriellesEtTertiairesHorsIndustriesPharmaceutiques,
|
|
||||||
|
|
||||||
EntiteDUnTOM,
|
|
||||||
FabricationExploitationImportationMedicamentsEtDispositifsMedicaux,
|
|
||||||
}
|
|
||||||
struct SituationDExercice {
|
|
||||||
/// Numéro identifiant la situation du PS parmi ses autres situations inscrites sur sa CPS
|
|
||||||
identifiant_situation: Byte,
|
|
||||||
mode_exercice: Option<ModeExercice>,
|
|
||||||
statut_exercice: Option<StatutExercice>,
|
|
||||||
secteur_activite: Option<SecteurActivite>,
|
|
||||||
structure_d_exercice: Option<StructureMedicale>,
|
|
||||||
}
|
|
@ -1,18 +1,14 @@
|
|||||||
use bitvec::index::BitIdx;
|
use bitvec::index::BitIdx;
|
||||||
use std::{error::Error, str::FromStr, vec::Vec};
|
use std::{error::Error, fmt, str::FromStr, vec::Vec};
|
||||||
|
|
||||||
use deku::{
|
use deku::{
|
||||||
bitvec::{BitStore, Msb0},
|
bitvec::{BitStore, Msb0}, ctx::ByteSize, deku_derive, reader::{Reader, ReaderRet}, DekuContainerRead, DekuError, DekuReader
|
||||||
ctx::ByteSize,
|
|
||||||
deku_derive,
|
|
||||||
reader::{Reader, ReaderRet},
|
|
||||||
DekuError, DekuReader,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[deku_derive(DekuRead)]
|
#[deku_derive(DekuRead)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
#[deku(endian = "big")]
|
#[deku(endian = "big")]
|
||||||
pub struct GroupId(u16);
|
pub(crate) struct GroupId(u16);
|
||||||
|
|
||||||
trait MapToDekuParseError<T> {
|
trait MapToDekuParseError<T> {
|
||||||
fn map_to_deku_parse_error(self) -> Result<T, DekuError>;
|
fn map_to_deku_parse_error(self) -> Result<T, DekuError>;
|
||||||
@ -26,30 +22,30 @@ impl<T, E: Error> MapToDekuParseError<T> for Result<T, E> {
|
|||||||
|
|
||||||
#[deku_derive(DekuRead)]
|
#[deku_derive(DekuRead)]
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct DataField {
|
pub(crate) struct DataField {
|
||||||
#[deku(reader = "read_size(deku::reader)")]
|
#[deku(reader = "read_size(deku::reader)")]
|
||||||
data_size: ByteSize,
|
pub(crate) data_size: ByteSize,
|
||||||
|
|
||||||
#[deku(bytes_read = "data_size.0")]
|
#[deku(bytes_read = "data_size.0")]
|
||||||
pub data: Vec<u8>,
|
pub(crate) data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deku_derive(DekuRead)]
|
#[deku_derive(DekuRead)]
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct BlockHeader {
|
pub(crate) struct BlockHeader {
|
||||||
pub group_id: GroupId,
|
pub(crate) group_id: GroupId,
|
||||||
|
|
||||||
#[deku(reader = "read_size(deku::reader)")]
|
#[deku(reader = "read_size(deku::reader)")]
|
||||||
pub data_size: ByteSize,
|
pub(crate) data_size: ByteSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deku_derive(DekuRead)]
|
#[deku_derive(DekuRead)]
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct DataBlock {
|
pub(crate) struct DataBlock {
|
||||||
pub header: BlockHeader,
|
pub(crate) header: BlockHeader,
|
||||||
|
|
||||||
#[deku(ctx = "header.group_id")]
|
#[deku(ctx = "header.group_id")]
|
||||||
pub inner: DataGroup,
|
pub(crate) inner: DataGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_size<R: std::io::Read>(reader: &mut Reader<R>) -> Result<ByteSize, DekuError> {
|
fn read_size<R: std::io::Read>(reader: &mut Reader<R>) -> Result<ByteSize, DekuError> {
|
||||||
@ -144,14 +140,109 @@ pub struct SESAMVitaleComponent {
|
|||||||
pub version: SESAMVitaleComponentVersion,
|
pub version: SESAMVitaleComponentVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deku_derive(DekuRead)]
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct ReaderConfiguration {}
|
||||||
|
|
||||||
#[deku_derive(DekuRead)]
|
#[deku_derive(DekuRead)]
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
#[deku(ctx = "group_id: GroupId", id = "group_id.0")]
|
#[deku(ctx = "group_id: GroupId", id = "group_id.0")]
|
||||||
pub enum DataGroup {
|
pub enum DataGroup {
|
||||||
#[deku(id = 60)]
|
#[deku(id = 60)]
|
||||||
ConfigurationHeader(ConfigurationHeader),
|
ConfigurationHeader(ConfigurationHeader),
|
||||||
#[deku(id = 67)]
|
#[deku(id = 61)]
|
||||||
PCSCReader(PCSCReader),
|
ReaderConfiguration(ReaderConfiguration),
|
||||||
#[deku(id = 64)]
|
#[deku(id = 64)]
|
||||||
SESAMVitaleComponent(SESAMVitaleComponent),
|
SESAMVitaleComponent(SESAMVitaleComponent),
|
||||||
|
#[deku(id = 67)]
|
||||||
|
PCSCReader(PCSCReader),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ConfigurationError {
|
||||||
|
MultipleConfigurationHeaders,
|
||||||
|
MissingConfigurationHeader,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ConfigurationError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
ConfigurationError::MultipleConfigurationHeaders => {
|
||||||
|
write!(f, "Multiple ConfigurationHeader blocks found")
|
||||||
|
}
|
||||||
|
ConfigurationError::MissingConfigurationHeader => {
|
||||||
|
write!(f, "Missing ConfigurationHeader block")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ConfigurationError {}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Configuration {
|
||||||
|
pub configuration_header: ConfigurationHeader,
|
||||||
|
pub reader_configurations: Vec<ReaderConfiguration>,
|
||||||
|
pub sesam_vitale_components: Vec<SESAMVitaleComponent>,
|
||||||
|
pub pcsc_readers: Vec<PCSCReader>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Vec<DataBlock>> for Configuration {
|
||||||
|
type Error = ConfigurationError;
|
||||||
|
|
||||||
|
fn try_from(data_blocks: Vec<DataBlock>) -> Result<Self, Self::Error> {
|
||||||
|
let mut configuration_header: Option<ConfigurationHeader> = None;
|
||||||
|
let mut reader_configurations: Vec<ReaderConfiguration> = Vec::new();
|
||||||
|
let mut sesam_vitale_components: Vec<SESAMVitaleComponent> = Vec::new();
|
||||||
|
let mut pcsc_readers: Vec<PCSCReader> = Vec::new();
|
||||||
|
|
||||||
|
for block in data_blocks {
|
||||||
|
match block.inner {
|
||||||
|
DataGroup::ConfigurationHeader(header) => {
|
||||||
|
if configuration_header.is_some() {
|
||||||
|
return Err(ConfigurationError::MultipleConfigurationHeaders);
|
||||||
|
}
|
||||||
|
configuration_header = Some(header);
|
||||||
|
}
|
||||||
|
DataGroup::ReaderConfiguration(configuration) => {
|
||||||
|
reader_configurations.push(configuration)
|
||||||
|
}
|
||||||
|
DataGroup::SESAMVitaleComponent(component) => {
|
||||||
|
sesam_vitale_components.push(component);
|
||||||
|
}
|
||||||
|
DataGroup::PCSCReader(reader) => {
|
||||||
|
pcsc_readers.push(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let configuration_header = match configuration_header {
|
||||||
|
Some(header) => header,
|
||||||
|
None => return Err(ConfigurationError::MissingConfigurationHeader),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
configuration_header,
|
||||||
|
reader_configurations,
|
||||||
|
sesam_vitale_components,
|
||||||
|
pcsc_readers,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_from_buffer<T: TryFrom<Vec<DataBlock>>>(buffer: &[u8]) -> Result<T, T::Error>{
|
||||||
|
let mut data_blocks: Vec<DataBlock> = Vec::new();
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
let mut remaining_buffer = buffer;
|
||||||
|
|
||||||
|
while !remaining_buffer.is_empty() {
|
||||||
|
// TODO: properly handle errors
|
||||||
|
let (rest, data_block) = DataBlock::from_bytes((remaining_buffer, offset)).unwrap();
|
||||||
|
|
||||||
|
data_blocks.push(data_block);
|
||||||
|
|
||||||
|
(remaining_buffer, offset) = rest;
|
||||||
|
};
|
||||||
|
|
||||||
|
T::try_from(data_blocks)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user