Skip to main content

uqa_core/memory/
string.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! UTF-8 buffers reserve old and replacement allocations before growing.
8
9use super::{replacement, MemoryBudget, MemoryError, MemoryReservation};
10
11#[derive(Debug)]
12pub struct BudgetedString {
13    value: String,
14    memory: MemoryReservation,
15}
16
17impl BudgetedString {
18    pub fn new(budget: &MemoryBudget) -> Self {
19        Self {
20            value: String::new(),
21            memory: budget.empty_reservation(),
22        }
23    }
24
25    pub fn capacity(&self) -> usize {
26        self.value.capacity()
27    }
28
29    pub fn reserve(&mut self, additional: usize) -> Result<(), MemoryError> {
30        let required = self
31            .value
32            .len()
33            .checked_add(additional)
34            .ok_or(MemoryError::SizeOverflow)?;
35        if required <= self.capacity() {
36            return Ok(());
37        }
38        let (capacity, memory) =
39            replacement::<u8>(self.memory.budget(), self.capacity(), required)?;
40        let mut value = String::new();
41        value.try_reserve_exact(capacity)?;
42        value.push_str(&self.value);
43        self.value = value;
44        self.memory = memory;
45        Ok(())
46    }
47
48    pub fn push_str(&mut self, text: &str) -> Result<(), MemoryError> {
49        self.reserve(text.len())?;
50        self.value.push_str(text);
51        Ok(())
52    }
53
54    pub fn push(&mut self, character: char) -> Result<(), MemoryError> {
55        self.reserve(character.len_utf8())?;
56        self.value.push(character);
57        Ok(())
58    }
59
60    pub fn into_parts(self) -> (String, MemoryReservation) {
61        (self.value, self.memory)
62    }
63}
64
65impl std::ops::Deref for BudgetedString {
66    type Target = str;
67
68    fn deref(&self) -> &str {
69        &self.value
70    }
71}