Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 17 additions & 23 deletions src/App.affine
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,32 @@

module App;

// TODO: Complete semantic implementation


/* === ORIGINAL RESCRIPT IMPLEMENTATION ===
// SPDX-License-Identifier: MPL-2.0
// DotMatrix-FilePrinter - App module
// Exports functions for the UI layer
// Uses proven library for formally verified safety operations

// Re-export bindings for JavaScript consumption
let checkGforth = Bindings.checkGforth
let previewStrike = Bindings.previewStrike
let executeStrike = Bindings.executeStrike
let verifySubstrate = Bindings.verifySubstrate
let checkGforth = Bindings::checkGforth;
let previewStrike = Bindings::previewStrike;
let executeStrike = Bindings::executeStrike;
let verifySubstrate = Bindings::verifySubstrate;

// Utilities (powered by proven library)
let stringToBytes = Bindings.stringToBytes
let bytesToString = Bindings.bytesToString
let parseByteString = Bindings.parseByteString
let isValidByte = Bindings.isValidByte
let isValidPath = Bindings.isValidPath
let bytesToHex = Bindings.bytesToHex
let bytesToHexCompact = Bindings.bytesToHexCompact
let hexToBytes = Bindings.hexToBytes
let stringToBytes = Bindings::stringToBytes;
let bytesToString = Bindings::bytesToString;
let parseByteString = Bindings::parseByteString;
let isValidByte = Bindings::isValidByte;
let isValidPath = Bindings::isValidPath;
let bytesToHex = Bindings::bytesToHex;
let bytesToHexCompact = Bindings::bytesToHexCompact;
let hexToBytes = Bindings::hexToBytes;

// For hex input mode
let decodeHex = Bindings.hexToBytes
let decodeHex = Bindings::hexToBytes;

// Constraint values for UI
let maxByte = Types.Constraints.maxByte
let forbiddenNbsp = Types.Constraints.forbiddenNbsp
let forbiddenUtf8 = Types.Constraints.forbiddenUtf8
let forbiddenBytes = Types.Constraints.forbiddenBytes

======================================== */
let maxByte = Types::Constraints::maxByte;
let forbiddenNbsp = Types::Constraints::forbiddenNbsp;
let forbiddenUtf8 = Types::Constraints::forbiddenUtf8;
let forbiddenBytes = Types::Constraints::forbiddenBytes;
121 changes: 58 additions & 63 deletions src/Bindings.affine
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,50 @@

module Bindings;

// TODO: Complete semantic implementation


/* === ORIGINAL RESCRIPT IMPLEMENTATION ===
// SPDX-License-Identifier: MPL-2.0
// Backend FFI Bindings for DotMatrix-FilePrinter
// Uses proven library for formally verified safety operations
// Uses RuntimeBridge for Gossamer/Tauri/browser dispatch

// Core backend API β€” delegates to RuntimeBridge for runtime detection
let invoke = RuntimeBridge.invoke
let invoke = RuntimeBridge::invoke;

// Re-export types
type contaminant = Types.contaminant
type previewResult = Types.previewResult
type verifyResult = Types.verifyResult
type contaminant = Types::contaminant
type previewResult = Types::previewResult
type verifyResult = Types::verifyResult

// Commands - these call the Rust backend

// Check if gforth is available
let checkGforth = (): promise<bool> => {
pub fn checkGforth() -> promise<Bool> {
invoke("check_gforth", ())
}

// Preview strike (dry-run)
let previewStrike = (bytes: array<int>): promise<previewResult> => {
pub fn previewStrike(bytes: [Int]) -> promise<previewResult> {
invoke("preview_forth_strike", {"bytes": bytes})
}

// Helper to create a rejected promise with an error message
let rejectWithMessage: string => promise<'a> = %raw(`
function(msg) { return Promise.reject(new Error(msg)); }
// TODO: Translate raw JS block to AffineScript extern or JS FFI
// let rejectWithMessage: string => promise<'a> = %raw(`
function(msg) { return Promise::reject(new Error(msg)); }
`)

// Execute strike via Forth kernel (with path validation using SafePath)
let executeStrike = (bytes: array<int>, path: string): promise<unit> => {
pub fn executeStrike(bytes: [Int], path: String) -> promise<unit> {
// Validate path doesn't contain traversal attacks
if !Proven_SafePath.isSafe(path) {
if !Proven_SafePath::isSafe(path) {
rejectWithMessage("Invalid path: contains traversal sequences")
} else {
invoke("execute_forth_strike", {"bytes": bytes, "path": path})
}
}

// Verify substrate file (with path validation using SafePath)
let verifySubstrate = (path: string): promise<verifyResult> => {
if !Proven_SafePath.isSafe(path) {
pub fn verifySubstrate(path: String) -> promise<verifyResult> {
if !Proven_SafePath::isSafe(path) {
rejectWithMessage("Invalid path: contains traversal sequences")
} else {
invoke("verify_substrate", {"path": path})
Expand All @@ -59,80 +56,78 @@ let verifySubstrate = (path: string): promise<verifyResult> => {

// Utilities using proven library

// Convert string to byte array using SafeString.toCodePoints
let stringToBytes = (str: string): array<int> => {
switch Proven_SafeString.toCodePoints(str) {
| Ok(bytes) => bytes
| Error(_) => [] // Return empty on non-ASCII input
// Convert String to byte array using SafeString::toCodePoints
pub fn stringToBytes(str: String) -> [Int] {
match Proven_SafeString::toCodePoints(str) {
Ok(bytes) => bytes
Error(_) => [] // Return empty on non-ASCII input
}
}

// Convert byte array to string using SafeString.fromCodePoints
let bytesToString = (bytes: array<int>): string => {
switch Proven_SafeString.fromCodePoints(bytes) {
| Ok(str) => str
| Error(_) => "" // Return empty on invalid code points
// Convert byte array to String using SafeString::fromCodePoints
pub fn bytesToString(bytes: [Int]) -> String {
match Proven_SafeString::fromCodePoints(bytes) {
Ok(str) => str
Error(_) => "" // Return empty on invalid code points
}
}

// Validate a single byte (uses SafeMath via Types.Constraints)
let isValidByte = (byte: int): bool => {
Types.Constraints.isValidByte(byte)
// Validate a single byte (uses SafeMath via Types::Constraints)
pub fn isValidByte(byte: Int) -> Bool {
Types::Constraints::isValidByte(byte)
}

// Validate path safety using SafePath
let isValidPath = (path: string): bool => {
Proven_SafePath.isSafe(path)
pub fn isValidPath(path: String) -> Bool {
Proven_SafePath::isSafe(path)
}

// Parse comma-separated bytes using SafeMath.fromString
let parseByteString = (str: string): result<array<int>, string> => {
let parts = str
->String.trim
->String.split(",")
->Array.map(String.trim)
->Array.filter(s => s->String.length > 0)
// Parse comma-separated bytes using SafeMath::fromString
let parseByteString = (str: String): result<[Int], String> => {
let parts = str;
->String::trim
->String::split(",")
->Array::map(String::trim)
->Array::filter(s => s->String::length > 0)

// Use SafeMath.fromString for safe integer parsing
let bytes = parts->Array.map(s => Proven_SafeMath.fromString(s))
// Use SafeMath::fromString for safe integer parsing
let bytes = parts->Array::map(s => Proven_SafeMath::fromString(s))

if bytes->Array.some(Option.isNone) {
if bytes->Array::some(Option::isNone) {
Error("Invalid byte value")
} else {
let values = bytes->Array.filterMap(x => x)
let invalid = values->Array.findIndex(b => !isValidByte(b))
let values = bytes->Array::filterMap(x => x)
let invalid = values->Array::findIndex(b => !isValidByte(b))
if invalid >= 0 {
Error(`Byte at position ${Int.toString(invalid)} is invalid`)
Error(`Byte at position ${Int::toString(invalid)} is invalid`)
} else {
Ok(values)
}
}
}

// Format bytes as spaced hex using SafeHex.encodeSpaced
let bytesToHex = (bytes: array<int>): string => {
switch Proven_SafeHex.encodeSpaced(bytes) {
| Ok(hex) => hex
| Error(_) => "" // Return empty on invalid bytes
// Format bytes as spaced hex using SafeHex::encodeSpaced
pub fn bytesToHex(bytes: [Int]) -> String {
match Proven_SafeHex::encodeSpaced(bytes) {
Ok(hex) => hex
Error(_) => "" // Return empty on invalid bytes
}
}

// Format bytes as compact hex (no spaces) using SafeHex.encode
let bytesToHexCompact = (bytes: array<int>): string => {
switch Proven_SafeHex.encode(bytes) {
| Ok(hex) => hex
| Error(_) => ""
// Format bytes as compact hex (no spaces) using SafeHex::encode
pub fn bytesToHexCompact(bytes: [Int]) -> String {
match Proven_SafeHex::encode(bytes) {
Ok(hex) => hex
Error(_) => ""
}
}

// Decode hex string to bytes using SafeHex.decode
let hexToBytes = (hexStr: string): result<array<int>, string> => {
switch Proven_SafeHex.decode(hexStr) {
| Ok(bytes) => Ok(bytes)
| Error(Proven_SafeHex.InvalidLength) => Error("Invalid hex length (must be even)")
| Error(Proven_SafeHex.InvalidCharacter) => Error("Invalid hex character")
| Error(Proven_SafeHex.EmptyInput) => Ok([])
// Decode hex String to bytes using SafeHex::decode
let hexToBytes = (hexStr: String): result<[Int], String> => {
match Proven_SafeHex::decode(hexStr) {
Ok(bytes) => Ok(bytes)
Error(Proven_SafeHex::InvalidLength) => Error("Invalid hex length (must be even)")
Error(Proven_SafeHex::InvalidCharacter) => Error("Invalid hex character")
Error(Proven_SafeHex::EmptyInput) => Ok([])
}
}

======================================== */
Loading
Loading