StringBuilder

struct StringBuilder

Incrementally constructs one valid UTF-8 string in a unique growable buffer.

byte_count <= capacity; the initialized prefix is valid UTF-8 after every public append. Growth doubles capacity, so repeated appends are amortized linear in the total bytes. finish transfers the allocation without copying.

Methods

mut func reserve_capacity(_ capacity: Int) -> Void

Ensures room for at least the requested number of bytes.

View Source
pub mut func reserve_capacity(_ capacity: Int) -> Void {
	if capacity <= self.capacity { return () }
	let fresh: ByteStorage = _byte_storage(capacity: capacity)
	_copy(from: self.storage.base, to: fresh.base, length: self.byte_count)
	self.storage = fresh
	self.capacity = capacity
}

mut func append(string value: String) -> Void

Appends every UTF-8 byte in value.

View Source
pub mut func append(string value: String) -> Void {
	self.append_view(value.as_substring())
}

mut func append(substring value: Substring) -> Void

Appends the borrowed byte range in value.

View Source
pub mut func append(substring value: Substring) -> Void {
	self.append_view(value)
}

mut func append(character value: Character) -> Void

Appends the complete grapheme cluster represented by value.

View Source
pub mut func append(character value: Character) -> Void {
	self.append_view(value.as_substring())
}

mut func append_scalar(_ scalar: Int) -> Void

Encodes one Unicode scalar and appends its UTF-8 bytes.

Values outside the scalar range, including surrogate code points, are replaced with U+FFFD. This keeps the builder's valid-UTF-8 invariant even when low-level Unicode algorithms supply an invalid integer.

View Source
pub mut func append_scalar(_ scalar: Int) -> Void {
	let valid: Int = if scalar < 0 || scalar > 1114111 || (scalar >= 55296 && scalar <= 57343) {
		65533
	} else {
		scalar
	}
	let bytes: Int = if valid < 128 {
		1
	} else {
		if valid < 2048 {
			2
		} else {
			if valid < 65536 {
				3
			} else {
				4
			}
		}
	}
	self.ensure_capacity(self.byte_count + bytes)
	if bytes == 1 {
		self.storage.set(index: self.byte_count, value: valid._toByte())
	} else {
		if bytes == 2 {
			self.storage.set(index: self.byte_count, value: (192 + valid / 64)._toByte())
			self.storage.set(
				index: self.byte_count + 1,
				value: (128 + valid - (valid / 64) * 64)._toByte()
			)
		} else {
			if bytes == 3 {
				self.storage.set(index: self.byte_count, value: (224 + valid / 4096)._toByte())
				self.storage.set(
					index: self.byte_count + 1,
					value: (128 + (valid / 64) - (valid / 4096) * 64)._toByte()
				)
				self.storage.set(
					index: self.byte_count + 2,
					value: (128 + valid - (valid / 64) * 64)._toByte()
				)
			} else {
				self.storage.set(
					index: self.byte_count,
					value: (240 + valid / 262144)._toByte()
				)
				self.storage.set(
					index: self.byte_count + 1,
					value: (128 + (valid / 4096) - (valid / 262144) * 64)._toByte()
				)
				self.storage.set(
					index: self.byte_count + 2,
					value: (128 + (valid / 64) - (valid / 4096) * 64)._toByte()
				)
				self.storage.set(
					index: self.byte_count + 3,
					value: (128 + valid - (valid / 64) * 64)._toByte()
				)
			}
		}
	}
	self.byte_count = self.byte_count + bytes
}

mut func append_line(_ string: String) -> Void

Appends string followed by a newline byte.

View Source
pub mut func append_line(_ string: String) -> Void {
	self.append_view(string.as_substring())
	self.append_view("\n".as_substring())
}

mut func clear() -> Void

Removes the accumulated contents while retaining allocated capacity.

View Source
pub mut func clear() -> Void {
	self.byte_count = 0
}

func utf8_count() -> Int

Returns the number of UTF-8 bytes.

View Source
pub func utf8_count() -> Int {
	self.byte_count
}

consuming func finish() -> String

Transfers the initialized buffer into an immutable String without copying.

The consumed builder is cleared before return so its destructor cannot release the allocation now owned by the string.

View Source
pub consuming func finish() -> String {
	let storage = self.storage
	let byte_count = self.byte_count
	let capacity = self.capacity
	self.storage = _byte_storage(capacity: 0)
	self.byte_count = 0
	self.capacity = 0
	String(base: storage, byte_count: byte_count, capacity: capacity)
}