structured_pades/
session.rs1use crate::error::{Error, ErrorKind, Limit, Result};
4use crate::source::Location;
5use core::cell::Cell;
6use structured_asn1::memory::{Execution, Memory, Work};
7use structured_asn1::{Encoding, Parser};
8
9#[derive(Debug, Clone, Copy)]
12pub struct Limits {
13 pub processing: structured_asn1::Limits,
16 pub max_objects: u64,
18 pub max_revisions: u32,
20 pub max_decoded: u64,
22}
23
24impl Default for Limits {
25 fn default() -> Self {
26 Self {
27 processing: structured_asn1::Limits::default(),
28 max_objects: 500_000,
29 max_revisions: 1_000,
30 max_decoded: 64 * 1024 * 1024,
31 }
32 }
33}
34
35pub struct Session {
41 parser: Parser,
42 limits: Limits,
43 objects: Cell<u64>,
44 revisions: Cell<u64>,
45 decoded: Cell<u64>,
46}
47
48impl Session {
49 #[must_use]
51 pub fn new(limits: Limits, memory: Memory) -> Self {
52 Self {
53 parser: Parser::new(Encoding::Der, limits.processing, memory),
54 limits,
55 objects: Cell::new(0),
56 revisions: Cell::new(0),
57 decoded: Cell::new(0),
58 }
59 }
60
61 #[must_use]
63 pub fn limits(&self) -> Limits {
64 self.limits
65 }
66
67 #[must_use]
70 pub fn execution(&self) -> Execution<'_> {
71 self.parser.execution_in(self.parser.memory())
72 }
73
74 #[must_use]
78 pub fn query<'a, W: Work>(&'a self, operation: &'a W) -> Execution<'a> {
79 operation.execution_for(&self.parser)
80 }
81
82 pub(crate) fn carried<'a, W: Work + 'a>(
83 &'a self,
84 bytes: &'a [u8],
85 operation: &W,
86 ) -> structured_asn1::Result<structured_asn1::Reader<'a>> {
87 operation.read_source(&self.parser, bytes, 0, Encoding::Der, 0)
88 }
89
90 pub(crate) fn owns(&self, reader: &structured_asn1::Reader<'_>) -> bool {
91 core::ptr::eq(core::ptr::from_ref(&self.parser), reader.parser())
92 }
93
94 pub(crate) fn decoded_remaining(&self) -> u64 {
95 self.limits.max_decoded - self.decoded.get()
96 }
97
98 pub fn object(&self, location: Location) -> Result<()> {
100 Self::admit(
101 &self.objects,
102 1,
103 self.limits.max_objects,
104 Limit::Objects,
105 location,
106 )
107 }
108
109 pub fn revision(&self, location: Location) -> Result<()> {
111 Self::admit(
112 &self.revisions,
113 1,
114 u64::from(self.limits.max_revisions),
115 Limit::Revisions,
116 location,
117 )
118 }
119
120 pub fn decode(&self, amount: u64, location: Location) -> Result<()> {
123 Self::admit(
124 &self.decoded,
125 amount,
126 self.limits.max_decoded,
127 Limit::Decoded,
128 location,
129 )
130 }
131
132 fn admit(
133 counter: &Cell<u64>,
134 amount: u64,
135 ceiling: u64,
136 limit: Limit,
137 location: Location,
138 ) -> Result<()> {
139 let spent = counter.get();
140 debug_assert!(spent <= ceiling);
141 if amount > ceiling - spent {
142 return Err(Error {
143 kind: ErrorKind::Limit(limit),
144 location,
145 });
146 }
147 counter.set(spent + amount);
148 Ok(())
149 }
150}