Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/development/std/path.nct

path.nct

//! Owned UTF-8 filesystem paths.
//!
//! Darwin permits non-UTF-8 path bytes. This type deliberately promises UTF-8
//! instead of misrepresenting every platform path as text.

use std/error.Error
use std/string.{String, bytes}

pub struct Utf8Path {
    text: String
}

construct Utf8Path {
    pub default func new(value: &str): Self! {
        validate(value)?
        return Utf8Path { text: String.copy(value) }
    }
}

pub func from_str(value: &str): Utf8Path! {
    return Utf8Path.new(value)?
}

pub func view(path: &Utf8Path): &str from path {
    return path.text.view()
}

pub func is_absolute(path: &Utf8Path): bool {
    let value: &str = path.text.view()
    return value.len() != 0 && bytes(value)[0] == 47
}

pub func join(path: &Utf8Path, child: &str): Utf8Path! {
    validate(child)?
    if child.len() != 0 && bytes(child)[0] == 47 {
        return Utf8Path.new(child)?
    }
    var result = String.copy(path.text.view())
    if result.len() != 0 && !result.ends_with("/") {
        result.push_str("/")
    }
    result.push_str(child)
    return Utf8Path { text: move result }
}

pub func validate(value: &str): void! {
    let raw = bytes(value)
    var offset: usize = 0
    while offset < raw.len() {
        if raw[offset] == 0 { return invalid_path() }
        offset = offset + 1
    }
    return
}

pub func invalid_path(): error {
    return Error.new("std.path.invalid_path", "UTF-8 path contains a NUL byte")
}

impl Utf8Path {
    pub method &self.view(): &str from self { return view(self) }
    pub method &self.is_absolute(): bool { return is_absolute(self) }
    pub method &self.join(child: &str): Utf8Path! { return join(self, child)? }
}