1#![deny(missing_docs)]
2
3use std::iter;
6use std::marker::PhantomData;
7
8use crate::binary::read::{ReadArray, ReadArrayCow, ReadScope, ReadUnchecked};
9use crate::binary::{I16Be, I32Be, I64Be, U16Be, U24Be, U32Be, I8, U8};
10use crate::error::WriteError;
11
12pub struct WriteBuffer {
14 data: Vec<u8>,
15}
16
17struct WriteSlice<'a> {
18 offset: usize,
19 data: &'a mut [u8],
20}
21
22pub struct WriteCounter {
24 count: usize,
25}
26
27struct NullWriter;
29
30pub struct Placeholder<T, HostType>
32where
33 T: WriteBinaryDep<HostType>,
34{
35 offset: usize,
36 length: usize,
37 marker: PhantomData<T>,
38 host: PhantomData<HostType>,
39}
40
41pub trait WriteBinary<HostType = Self> {
43 type Output;
45
46 fn write<C: WriteContext>(ctxt: &mut C, val: HostType) -> Result<Self::Output, WriteError>;
48}
49
50pub trait WriteBinaryDep<HostType = Self> {
53 type Args;
55 type Output;
57
58 fn write_dep<C: WriteContext>(
60 ctxt: &mut C,
61 val: HostType,
62 args: Self::Args,
63 ) -> Result<Self::Output, WriteError>;
64}
65
66pub trait WriteContext {
68 fn write_array<'a, T>(&mut self, array: &ReadArray<'a, T>) -> Result<(), WriteError>
70 where
71 Self: Sized,
72 T: ReadUnchecked + WriteBinary<<T as ReadUnchecked>::HostType>,
73 {
74 <&ReadArray<'_, _>>::write(self, array)
75 }
76
77 fn write_vec<T, HostType>(&mut self, vec: Vec<HostType>) -> Result<(), WriteError>
79 where
80 Self: Sized,
81 T: WriteBinary<HostType>,
82 {
83 for val in vec {
84 T::write(self, val)?;
85 }
86
87 Ok(())
88 }
89
90 fn write_iter<T, HostType>(
92 &mut self,
93 iter: impl Iterator<Item = HostType>,
94 ) -> Result<(), WriteError>
95 where
96 Self: Sized,
97 T: WriteBinary<HostType>,
98 {
99 for val in iter {
100 T::write(self, val)?;
101 }
102
103 Ok(())
104 }
105
106 fn write_bytes(&mut self, data: &[u8]) -> Result<(), WriteError>;
108
109 fn write_zeros(&mut self, count: usize) -> Result<(), WriteError>;
111
112 fn bytes_written(&self) -> usize;
114
115 fn placeholder<'a, T, HostType>(&mut self) -> Result<Placeholder<T, HostType>, WriteError>
117 where
118 T: WriteBinary<HostType> + ReadUnchecked,
119 {
120 let offset = self.bytes_written();
121 self.write_zeros(T::SIZE)?;
122
123 Ok(Placeholder {
124 offset,
125 length: T::SIZE,
126 marker: PhantomData,
127 host: PhantomData,
128 })
129 }
130
131 fn reserve<'a, T, HostType>(
133 &mut self,
134 count: usize,
135 ) -> Result<Placeholder<T, &'a HostType>, WriteError>
136 where
137 T: WriteBinaryDep<&'a HostType>,
138 {
139 let offset = self.bytes_written();
140 self.write_zeros(count)?;
141
142 Ok(Placeholder {
143 offset,
144 length: count,
145 marker: PhantomData,
146 host: PhantomData,
147 })
148 }
149
150 fn placeholder_array<'a, T, HostType>(
152 &mut self,
153 count: usize,
154 ) -> Result<Vec<Placeholder<T, HostType>>, WriteError>
155 where
156 T: WriteBinary<HostType> + ReadUnchecked,
157 {
158 (0..count)
159 .map(|_| self.placeholder::<T, HostType>())
160 .collect()
161 }
162
163 fn write_placeholder<T, HostType>(
165 &mut self,
166 placeholder: Placeholder<T, HostType>,
167 val: HostType,
168 ) -> Result<T::Output, WriteError>
169 where
170 T: WriteBinary<HostType>;
171
172 fn write_placeholder_dep<T, HostType>(
175 &mut self,
176 placeholder: Placeholder<T, HostType>,
177 val: HostType,
178 args: T::Args,
179 ) -> Result<T::Output, WriteError>
180 where
181 T: WriteBinaryDep<HostType>;
182}
183
184pub fn buffer<HostType, T: WriteBinaryDep<HostType>>(
186 writeable: HostType,
187 args: T::Args,
188) -> Result<(T::Output, WriteBuffer), WriteError> {
189 let mut buffer = WriteBuffer::new();
190 let output = T::write_dep(&mut buffer, writeable, args)?;
191 Ok((output, buffer))
192}
193
194impl<T, HostType> WriteBinaryDep<HostType> for T
195where
196 T: WriteBinary<HostType>,
197{
198 type Args = ();
199 type Output = T::Output;
200
201 fn write_dep<C: WriteContext>(
202 ctxt: &mut C,
203 val: HostType,
204 (): Self::Args,
205 ) -> Result<Self::Output, WriteError> {
206 T::write(ctxt, val)
207 }
208}
209
210impl<T> WriteBinary<T> for U8
211where
212 T: Into<u8>,
213{
214 type Output = ();
215
216 fn write<C: WriteContext>(ctxt: &mut C, t: T) -> Result<(), WriteError> {
217 let val: u8 = t.into();
218 ctxt.write_bytes(&[val])
219 }
220}
221
222impl<T> WriteBinary<T> for I8
223where
224 T: Into<i8>,
225{
226 type Output = ();
227
228 fn write<C: WriteContext>(ctxt: &mut C, t: T) -> Result<(), WriteError> {
229 let val: i8 = t.into();
230 ctxt.write_bytes(&val.to_be_bytes())
231 }
232}
233
234impl<T> WriteBinary<T> for I16Be
235where
236 T: Into<i16>,
237{
238 type Output = ();
239
240 fn write<C: WriteContext>(ctxt: &mut C, t: T) -> Result<(), WriteError> {
241 let val: i16 = t.into();
242 ctxt.write_bytes(&val.to_be_bytes())
243 }
244}
245
246impl<T> WriteBinary<T> for U16Be
247where
248 T: Into<u16>,
249{
250 type Output = ();
251
252 fn write<C: WriteContext>(ctxt: &mut C, t: T) -> Result<(), WriteError> {
253 let val: u16 = t.into();
254 ctxt.write_bytes(&val.to_be_bytes())
255 }
256}
257
258impl<T> WriteBinary<T> for U24Be
259where
260 T: Into<u32>,
261{
262 type Output = ();
263
264 fn write<C: WriteContext>(ctxt: &mut C, t: T) -> Result<(), WriteError> {
265 let val: u32 = t.into();
266 if val > 0xFF_FFFF {
267 return Err(WriteError::BadValue);
268 }
269 ctxt.write_bytes(&val.to_be_bytes()[1..4])
270 }
271}
272
273impl<T> WriteBinary<T> for I32Be
274where
275 T: Into<i32>,
276{
277 type Output = ();
278
279 fn write<C: WriteContext>(ctxt: &mut C, t: T) -> Result<(), WriteError> {
280 let val: i32 = t.into();
281 ctxt.write_bytes(&val.to_be_bytes())
282 }
283}
284
285impl<T> WriteBinary<T> for U32Be
286where
287 T: Into<u32>,
288{
289 type Output = ();
290
291 fn write<C: WriteContext>(ctxt: &mut C, t: T) -> Result<(), WriteError> {
292 let val: u32 = t.into();
293 ctxt.write_bytes(&val.to_be_bytes())
294 }
295}
296
297impl<T> WriteBinary<T> for I64Be
298where
299 T: Into<i64>,
300{
301 type Output = ();
302
303 fn write<C: WriteContext>(ctxt: &mut C, t: T) -> Result<(), WriteError> {
304 let val: i64 = t.into();
305 ctxt.write_bytes(&val.to_be_bytes())
306 }
307}
308
309impl WriteContext for WriteBuffer {
310 fn write_bytes(&mut self, data: &[u8]) -> Result<(), WriteError> {
311 self.data.extend(data.iter());
312 Ok(())
313 }
314
315 fn write_zeros(&mut self, count: usize) -> Result<(), WriteError> {
316 let zeros = iter::repeat(0).take(count);
317 self.data.extend(zeros);
318 Ok(())
319 }
320
321 fn bytes_written(&self) -> usize {
322 self.data.len()
323 }
324
325 fn write_placeholder<T, HostType>(
326 &mut self,
327 placeholder: Placeholder<T, HostType>,
328 val: HostType,
329 ) -> Result<T::Output, WriteError>
330 where
331 T: WriteBinary<HostType>,
332 {
333 let data = &mut self.data[placeholder.offset..];
334 let data = &mut data[0..placeholder.length];
335 let mut slice = WriteSlice { offset: 0, data };
336 T::write(&mut slice, val)
337 }
338
339 fn write_placeholder_dep<T, HostType>(
340 &mut self,
341 placeholder: Placeholder<T, HostType>,
342 val: HostType,
343 args: T::Args,
344 ) -> Result<T::Output, WriteError>
345 where
346 T: WriteBinaryDep<HostType>,
347 {
348 let data = &mut self.data[placeholder.offset..];
349 let data = &mut data[0..placeholder.length];
350 let mut slice = WriteSlice { offset: 0, data };
351 T::write_dep(&mut slice, val, args)
352 }
353}
354
355impl<'a> WriteContext for WriteSlice<'a> {
356 fn write_bytes(&mut self, data: &[u8]) -> Result<(), WriteError> {
357 let data_len = data.len();
358 let self_len = self.data.len();
359
360 if data_len <= self_len {
361 let subslice = &mut self.data[self.offset..][0..data_len];
362 subslice.copy_from_slice(data);
363 self.offset += data_len;
364 Ok(())
365 } else {
366 Err(WriteError::PlaceholderMismatch)
367 }
368 }
369
370 fn write_zeros(&mut self, count: usize) -> Result<(), WriteError> {
371 for i in 0..count.min(self.data.len()) {
372 self.data[i] = 0;
373 }
374
375 Ok(())
376 }
377
378 fn bytes_written(&self) -> usize {
379 self.data.len()
380 }
381
382 fn write_placeholder<T, HostType>(
383 &mut self,
384 _placeholder: Placeholder<T, HostType>,
385 _val: HostType,
386 ) -> Result<T::Output, WriteError>
387 where
388 T: WriteBinary<HostType>,
389 {
390 unimplemented!()
391 }
392
393 fn write_placeholder_dep<T, HostType>(
394 &mut self,
395 _placeholder: Placeholder<T, HostType>,
396 _val: HostType,
397 _args: T::Args,
398 ) -> Result<T::Output, WriteError>
399 where
400 T: WriteBinaryDep<HostType>,
401 {
402 unimplemented!()
403 }
404}
405
406impl WriteContext for WriteCounter {
407 fn write_bytes(&mut self, data: &[u8]) -> Result<(), WriteError> {
408 self.count += data.len();
409 Ok(())
410 }
411
412 fn write_zeros(&mut self, count: usize) -> Result<(), WriteError> {
413 self.count += count;
414 Ok(())
415 }
416
417 fn bytes_written(&self) -> usize {
418 self.count
419 }
420
421 fn write_placeholder<T, HostType>(
422 &mut self,
423 _placeholder: Placeholder<T, HostType>,
424 val: HostType,
425 ) -> Result<T::Output, WriteError>
426 where
427 T: WriteBinary<HostType>,
428 {
429 let mut null = NullWriter;
430 T::write(&mut null, val)
431 }
432
433 fn write_placeholder_dep<T, HostType>(
434 &mut self,
435 _placeholder: Placeholder<T, HostType>,
436 val: HostType,
437 args: T::Args,
438 ) -> Result<T::Output, WriteError>
439 where
440 T: WriteBinaryDep<HostType>,
441 {
442 let mut null = NullWriter;
443 T::write_dep(&mut null, val, args)
444 }
445}
446
447impl WriteContext for NullWriter {
448 fn write_bytes(&mut self, _data: &[u8]) -> Result<(), WriteError> {
449 Ok(())
450 }
451
452 fn write_zeros(&mut self, _count: usize) -> Result<(), WriteError> {
453 Ok(())
454 }
455
456 fn bytes_written(&self) -> usize {
457 0
458 }
459
460 fn write_placeholder<T, HostType>(
461 &mut self,
462 _placeholder: Placeholder<T, HostType>,
463 _val: HostType,
464 ) -> Result<T::Output, WriteError>
465 where
466 T: WriteBinary<HostType>,
467 {
468 unimplemented!()
469 }
470
471 fn write_placeholder_dep<T, HostType>(
472 &mut self,
473 _placeholder: Placeholder<T, HostType>,
474 _val: HostType,
475 _args: T::Args,
476 ) -> Result<T::Output, WriteError>
477 where
478 T: WriteBinaryDep<HostType>,
479 {
480 unimplemented!()
481 }
482}
483
484impl<'a, T> WriteBinary for &ReadArray<'a, T>
485where
486 T: ReadUnchecked + WriteBinary<<T as ReadUnchecked>::HostType>,
487{
488 type Output = ();
489
490 fn write<C: WriteContext>(ctxt: &mut C, array: Self) -> Result<(), WriteError> {
491 for val in array.into_iter() {
492 T::write(ctxt, val)?;
493 }
494
495 Ok(())
496 }
497}
498
499impl<'a, T> WriteBinary<&Self> for ReadArrayCow<'a, T>
500where
501 T: ReadUnchecked + WriteBinary<<T as ReadUnchecked>::HostType>,
502 T::HostType: Copy,
503{
504 type Output = ();
505
506 fn write<C: WriteContext>(ctxt: &mut C, array: &Self) -> Result<(), WriteError> {
507 for val in array.iter() {
508 T::write(ctxt, val)?;
509 }
510
511 Ok(())
512 }
513}
514
515impl<'a> WriteBinary for ReadScope<'a> {
516 type Output = ();
517
518 fn write<C: WriteContext>(ctxt: &mut C, scope: Self) -> Result<(), WriteError> {
519 ctxt.write_bytes(scope.data())
520 }
521}
522
523impl WriteBuffer {
524 pub fn new() -> Self {
526 WriteBuffer { data: Vec::new() }
527 }
528
529 pub fn bytes(&self) -> &[u8] {
531 &self.data
532 }
533
534 pub fn clear(&mut self) {
536 self.data.clear();
537 }
538
539 pub fn len(&self) -> usize {
541 self.data.len()
542 }
543
544 pub fn into_inner(self) -> Vec<u8> {
546 self.data
547 }
548}
549
550impl WriteCounter {
551 pub fn new() -> Self {
553 WriteCounter { count: 0 }
554 }
555}
556
557#[cfg(test)]
558mod tests {
559 use super::*;
560 use crate::tag;
561
562 struct TestTable {
563 tag: u32,
564 }
565
566 struct BigStruct {
567 tag: u32,
568 }
569
570 impl WriteBinary<Self> for TestTable {
571 type Output = ();
572
573 fn write<C: WriteContext>(ctxt: &mut C, val: Self) -> Result<(), WriteError> {
574 U32Be::write(ctxt, val.tag)
575 }
576 }
577
578 impl WriteBinary<&Self> for BigStruct {
579 type Output = ();
580
581 fn write<C: WriteContext>(ctxt: &mut C, val: &Self) -> Result<(), WriteError> {
582 U32Be::write(ctxt, val.tag)
583 }
584 }
585
586 #[test]
587 fn test_basic() {
588 let mut ctxt = WriteBuffer::new();
589 let table = TestTable { tag: tag::GLYF };
590 let big = BigStruct { tag: tag::BLOC };
591
592 TestTable::write(&mut ctxt, table).unwrap();
593 BigStruct::write(&mut ctxt, &big).unwrap();
594
595 assert_eq!(ctxt.bytes(), b"glyfbloc")
596 }
597
598 #[test]
599 fn test_write_u24be() {
600 let mut ctxt = WriteBuffer::new();
601 U24Be::write(&mut ctxt, 0x10203u32).unwrap();
602 assert_eq!(ctxt.bytes(), &[1, 2, 3]);
603
604 match U24Be::write(&mut ctxt, std::u32::MAX) {
606 Err(WriteError::BadValue) => {}
607 _ => panic!("Expected WriteError::BadValue"),
608 }
609 }
610
611 #[test]
612 fn test_write_placeholder() {
613 let mut ctxt = WriteBuffer::new();
614 U8::write(&mut ctxt, 1).unwrap();
615 let placeholder = ctxt.placeholder::<U16Be, u16>().unwrap();
616 U8::write(&mut ctxt, 3).unwrap();
617 ctxt.write_placeholder(placeholder, 2).unwrap();
618 assert_eq!(ctxt.bytes(), &[1, 0, 2, 3]);
619 }
620
621 #[test]
622 fn test_write_placeholder_overflow() {
623 let mut ctxt = WriteBuffer::new();
625 let placeholder = ctxt.reserve::<BigStruct, _>(1).unwrap();
626 let value = BigStruct { tag: 1234 };
627 assert!(ctxt.write_placeholder(placeholder, &value).is_err());
628 }
629}