use std::marker::PhantomData;
use crate::{
alloc::{Allocator, Object},
error::{Result, from_result},
ffi,
};
#[derive(Debug)]
pub struct Parser<'alloc>(Object<'alloc, ffi::GhosttyOscParser>);
impl<'alloc> Parser<'alloc> {
pub fn new() -> Result<Self> {
unsafe { Self::new_inner(std::ptr::null()) }
}
pub fn new_with_alloc<'ctx: 'alloc, Ctx>(alloc: &'alloc Allocator<'ctx, Ctx>) -> Result<Self> {
unsafe { Self::new_inner(alloc.to_raw()) }
}
unsafe fn new_inner(alloc: *const ffi::GhosttyAllocator) -> Result<Self> {
let mut raw: ffi::GhosttyOscParser_ptr = std::ptr::null_mut();
let result = unsafe { ffi::ghostty_osc_new(alloc, &raw mut raw) };
from_result(result)?;
Ok(Self(Object::new(raw)?))
}
pub fn reset(&mut self) {
unsafe { ffi::ghostty_osc_reset(self.0.as_raw()) }
}
pub fn next_byte(&mut self, byte: u8) {
unsafe { ffi::ghostty_osc_next(self.0.as_raw(), byte) }
}
#[expect(clippy::missing_panics_doc, reason = "internal invariant")]
pub fn end<'p>(&'p mut self, terminator: u8) -> Command<'p, 'alloc> {
let raw = unsafe { ffi::ghostty_osc_end(self.0.as_raw(), terminator) };
Command {
inner: Object::new(raw).expect("command must not be null"),
_parser: PhantomData,
}
}
}
impl Drop for Parser<'_> {
fn drop(&mut self) {
unsafe { ffi::ghostty_osc_free(self.0.as_raw()) }
}
}
#[derive(Debug)]
pub struct Command<'p, 'alloc> {
inner: Object<'alloc, ffi::GhosttyOscCommand>,
_parser: PhantomData<&'p Parser<'alloc>>,
}
impl Command<'_, '_> {
#[must_use]
pub fn command_type(&self) -> CommandType {
CommandType::try_from(unsafe { ffi::ghostty_osc_command_type(self.inner.as_raw()) })
.unwrap_or_default()
}
}
#[expect(missing_docs, reason = "missing upstream docs")]
#[repr(u32)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, int_enum::IntEnum)]
pub enum CommandType {
#[default]
Invalid = ffi::GhosttyOscCommandType_GHOSTTY_OSC_COMMAND_INVALID,
}