use crate::{
container::{DS, XADES},
xml::Name,
};
use structured_asn1::memory::{MemoryError, Work};
mod basic;
mod material;
mod timestamp;
pub use basic::{Basic, BasicReferences, DataObject, ReferenceKind};
pub use material::write_material;
pub use material::{Material, MaterialKind, Materials};
pub use timestamp::{Timestamp, TimestampKind};
mod augmentation;
pub use augmentation::{
Augmentation, Checked, CheckedFor, InputResult, PreparationError, Presence, ResponseCheck,
ResponseError, ResponseResult, Transaction,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Datatype {
String,
Id,
AnyUri,
ZonedDateTime,
}
#[derive(Debug, Clone, Copy)]
pub struct Value<'a> {
pub lexical: &'a str,
pub datatype: Datatype,
}
#[derive(Debug, Clone, Copy)]
pub enum Event<'a> {
Begin(Name<'static>),
Attribute(Name<'static>, Value<'a>),
Text(Value<'a>),
Binary(&'a [u8]),
End,
}
pub trait Writer {
type Error;
fn write<W: Work>(&mut self, event: Event<'_>, work: &W) -> Result<(), Self::Error>;
}
#[derive(Debug)]
pub enum Error<E> {
Writer(E),
Resource(MemoryError),
Value(&'static str),
Foreign,
Prerequisites,
}
pub(crate) const fn name(namespace: &'static str, local: &'static str) -> Name<'static> {
Name { namespace, local }
}
pub(crate) const fn attr(local: &'static str) -> Name<'static> {
name("", local)
}
pub(crate) fn same_parent<N: Copy + Eq + structured_asn1::memory::HashWork, W: Work>(
left: Option<N>,
right: Option<N>,
work: &W,
) -> Result<bool, MemoryError> {
match (left, right) {
(Some(left), Some(right)) => structured_ltv::source::equal_id(left, right, work),
(None, None) => Ok(true),
(Some(_), None) | (None, Some(_)) => Ok(false),
}
}
pub(crate) struct Emit<'a, B: Writer, W: Work> {
pub writer: &'a mut B,
pub work: &'a W,
}
impl<B: Writer, W: Work> Emit<'_, B, W> {
pub fn event(&mut self, event: Event<'_>) -> Result<(), Error<B::Error>> {
self.work.charge_work(1).map_err(Error::Resource)?;
self.writer.write(event, self.work).map_err(Error::Writer)
}
pub fn begin(
&mut self,
namespace: &'static str,
local: &'static str,
) -> Result<(), Error<B::Error>> {
self.event(Event::Begin(name(namespace, local)))
}
pub fn end(&mut self) -> Result<(), Error<B::Error>> {
self.event(Event::End)
}
pub fn attribute(&mut self, local: &'static str, value: &str) -> Result<(), Error<B::Error>> {
let datatype = match local {
"Id" => Datatype::Id,
"Target" | "ObjectReference" | "Algorithm" => Datatype::AnyUri,
_ => Datatype::String,
};
self.event(Event::Attribute(
attr(local),
Value {
lexical: value,
datatype,
},
))
}
pub fn text(
&mut self,
namespace: &'static str,
local: &'static str,
value: &str,
) -> Result<(), Error<B::Error>> {
self.begin(namespace, local)?;
self.event(Event::Text(Value {
lexical: value,
datatype: Datatype::String,
}))?;
self.end()
}
pub fn binary(
&mut self,
namespace: &'static str,
local: &'static str,
value: &[u8],
) -> Result<(), Error<B::Error>> {
self.begin(namespace, local)?;
self.event(Event::Binary(value))?;
self.end()
}
pub fn digest(&mut self, method: &str, value: &[u8]) -> Result<(), Error<B::Error>> {
self.begin(DS, "DigestMethod")?;
self.attribute("Algorithm", method)?;
self.end()?;
self.binary(DS, "DigestValue", value)
}
}