1use std::ffi::OsString;
7use std::mem;
8use std::ops::Range;
9use std::path::PathBuf;
10
11use crate::arena::{ArenaString, scratch_arena};
12use crate::helpers::ReplaceRange as _;
13
14pub trait ReadableDocument {
16 fn read_forward(&self, off: usize) -> &[u8];
27
28 fn read_backward(&self, off: usize) -> &[u8];
39}
40
41pub trait WriteableDocument: ReadableDocument {
43 fn replace(&mut self, range: Range<usize>, replacement: &[u8]);
50}
51
52impl ReadableDocument for &[u8] {
53 fn read_forward(&self, off: usize) -> &[u8] {
54 let s = *self;
55 &s[off.min(s.len())..]
56 }
57
58 fn read_backward(&self, off: usize) -> &[u8] {
59 let s = *self;
60 &s[..off.min(s.len())]
61 }
62}
63
64impl ReadableDocument for String {
65 fn read_forward(&self, off: usize) -> &[u8] {
66 let s = self.as_bytes();
67 &s[off.min(s.len())..]
68 }
69
70 fn read_backward(&self, off: usize) -> &[u8] {
71 let s = self.as_bytes();
72 &s[..off.min(s.len())]
73 }
74}
75
76impl WriteableDocument for String {
77 fn replace(&mut self, range: Range<usize>, replacement: &[u8]) {
78 let scratch = scratch_arena(None);
80 let utf8 = ArenaString::from_utf8_lossy(&scratch, replacement);
81 let src = match &utf8 {
82 Ok(s) => s,
83 Err(s) => s.as_str(),
84 };
85
86 unsafe { self.as_mut_vec() }.replace_range(range, src.as_bytes());
88 }
89}
90
91impl ReadableDocument for PathBuf {
92 fn read_forward(&self, off: usize) -> &[u8] {
93 let s = self.as_os_str().as_encoded_bytes();
94 &s[off.min(s.len())..]
95 }
96
97 fn read_backward(&self, off: usize) -> &[u8] {
98 let s = self.as_os_str().as_encoded_bytes();
99 &s[..off.min(s.len())]
100 }
101}
102
103impl WriteableDocument for PathBuf {
104 fn replace(&mut self, range: Range<usize>, replacement: &[u8]) {
105 let mut vec = mem::take(self).into_os_string().into_encoded_bytes();
106 vec.replace_range(range, replacement);
107 *self = unsafe { Self::from(OsString::from_encoded_bytes_unchecked(vec)) };
108 }
109}