Under heavy development. This site describes the intended 1.0 language. Current features and performance vary. Development status
Sn50SnThe SnAPI programming language
0.2.0 Preview 1 · Frozen documentation

ExtendedAttributeWriteMode

Selects one native extended-attribute creation/update policy. These cases are semantic identities, not target flags. No implicit fallback turns CreateNew into replacement or ReplaceExisting into creation. Values own no resource and allocate nothing; ordinary shared mutation needs synchronization.

Sn is under heavy development. Reference extracted from this release’s bundled standard library. Public API examples are not an exhaustive compatibility test. Read the matching release guide for tested workflows and limitations. Read the status →

Module std.fs

import std.fs;

Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.

ExtendedAttributeWriteMode

pub enum ExtendedAttributeWriteMode

Selects one native extended-attribute creation/update policy. These cases are semantic identities, not target flags. No implicit fallback turns CreateNew into replacement or ReplaceExisting into creation. Values own no resource and allocate nothing; ordinary shared mutation needs synchronization.

Example

module example.file_attributes;
from std.process import ProgramInputs;
from std.fs import Path;
from std.collections import Vector;
from std.fs import File;
from std.io import IoError;
from std.prelude import Result;
fn ReplaceOwnedAttribute(Opened: mut File&) -> Result<void, IoError> {
    let Name: byte[13] = [0x75_byte, 0x73_byte, 0x65_byte, 0x72_byte, 0x2E_byte, 0x73_byte, 0x6E_byte, 0x2D_byte, 0x70_byte, 0x6C_byte, 0x61_byte, 0x6E_byte, 0x38_byte];
    let Bytes: byte[2] = [0_byte, 0xFF_byte];
    let Empty: byte[0] = [];
    // The caller reserves this name for this workflow and retains the file loan.
    switch Opened.RemoveExtendedAttribute(Name) {
        case .Ok => {}
        case .Err { Error = PatternPayload5032 } => {
            switch PatternPayload5032 {
                case .Failure { Reason = PatternPayload5033 } if (PatternPayload5033 is .NotFound) => {}
                default => { let Error = PatternPayload5032; return .Err { Error = Error }; }
            }
        }
    }
    let Missing = {
        var MissingResult = Opened.ReadExtendedAttribute(Name);
        switch MissingResult {
            case .Ok { Value = MissingPayload: mut Vector<byte>?& } => break move(MissingPayload);
            case .Err { Error = Error } => return .Err { Error = Error };
        }
    };
    if Missing is .Some { Value = _ } { return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } }; }
    switch Opened.WriteExtendedAttribute(Name, Bytes, .CreateNew) { case .Ok => {} case .Err { Error = Error } => return .Err { Error = Error }; }
    var Read = {
        var ReadResult = Opened.ReadExtendedAttribute(Name);
        switch ReadResult {
            case .Ok { Value = ReadPayload: mut Vector<byte>?& } => break move(ReadPayload);
            case .Err { Error = Error } => return .Err { Error = Error };
        }
    };
    var Owned = {
        // Scoped writable carriers end immediately after explicit payload transfer.
        var OwnedCarrier = move(Read);
        switch OwnedCarrier {
            case .Some { Value = Value: mut Vector<byte>& } => break move(Value);
            case .None => return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } };
        }
    };
    if Owned.Length != 2 || Owned[0] != 0_byte || Owned[1] != 0xFF_byte { return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } }; }
    switch Opened.WriteExtendedAttribute(Name, Bytes, .CreateNew) {
        case .Err { Error = PatternPayload5034 } => {
            switch PatternPayload5034 {
                case .Failure { Reason = PatternPayload5035 } if (PatternPayload5035 is .AlreadyExists) => {}
                default => { let Error = PatternPayload5034; return .Err { Error = Error }; }
            }
        }
        case .Ok => return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } };
    }
    switch Opened.WriteExtendedAttribute(Name, Empty, .ReplaceExisting) { case .Ok => {} case .Err { Error = Error } => return .Err { Error = Error }; }
    var Present = {
        var PresentResult = Opened.ReadExtendedAttribute(Name);
        switch PresentResult {
            case .Ok { Value = PresentPayload: mut Vector<byte>?& } => break move(PresentPayload);
            case .Err { Error = Error } => return .Err { Error = Error };
        }
    };
    switch move(Present) {
        case .Some { Value = Value } => { if Value.Length != 0 { return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } }; } }
        case .None => return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } };
    }
    // Upsert remains an explicit choice, even when the name already exists.
    switch Opened.WriteExtendedAttribute(Name, Bytes, .Upsert) { case .Ok => {} case .Err { Error = Error } => return .Err { Error = Error }; }
    var Names = {
        var NamesCreation = Opened.DiscoverExtendedAttributeNames();
        switch NamesCreation {
            case .Ok { Value = Value: mut Vector<Vector<byte>>& } => break move(Value);
            case .Err { Error = Error } => return .Err { Error = Error };
        }
    };
    var Found = false;
    for Candidate in Names.AsSlice() {
        if Candidate.Length == Name.Length {
            var Equal = true;
            var Index: usize = 0;
            while Index < Name.Length { if Candidate[Index] != Name[Index] { Equal = false; } Index += 1; }
            if Equal { Found = true; }
        }
    }
    if !Found { return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } }; }
    return Opened.RemoveExtendedAttribute(Name);
}

// Supply absolute paths to exclusively owned, disposable fixtures as arguments.
fn Main(Inputs: ProgramInputs) -> i32 {
    if Inputs.Arguments().Length != 2 { return 20; }
    let OwnedPathText = switch Inputs.Arguments()[1].TryViewUtf8() { case .Some { Value = Text } => break Text; case .None => return 21; };
    var OwnedPath = {
        var Creation = Path.TryCreate(OwnedPathText);
        switch Creation { case .Ok { Value = Created: mut Path& } => break move(Created); case .Err => return 22; }
    };
    var Opened = {
        var Creation = File.TryOpen(OwnedPath.View, .ReadWrite);
        switch Creation { case .Ok { Value = Created: mut File& } => break move(Created); case .Err => return 23; }
    };
    let Outcome = ReplaceOwnedAttribute(Opened);
    // End every operation's receiver loan before closing the sole native owner.
    let Closed = Opened.Close();
    if Outcome is .Err { Error = _ } { return 27; }
    if Closed is .Err { Error = _ } { return 28; }
    return 0;
}

ExtendedAttributeWriteMode.Upsert

Upsert;

Creates or replaces the named value.

ExtendedAttributeWriteMode.CreateNew

CreateNew;

Creates only, failing AlreadyExists when present.

ExtendedAttributeWriteMode.ReplaceExisting

ReplaceExisting;

Replaces only, failing NotFound when absent.

Documentation snapshot: October 24, 2026 About versions ↗
Searching Development · language & standard library