Modules
Oxide uses Rust's module system with intuitive keywords and visibility modifiers.
Inline Modules
Define modules within a file:
module utils {
public fn helper(): Int { 42 }
fn privateHelper(): Int { 0 } // Private to module
}
// Access module items using dot syntax
let x = utils.helper()
Transpiles to:
mod utils {
pub fn helper() -> isize { 42 }
fn private_helper() -> isize { 0 }
}
let x = utils::helper();
Nested Modules
module outer {
public module inner {
public fn deepFunc(): String { "deep" }
}
public fn outerFunc(): Int { 100 }
}
// Access nested items using dot syntax
let s = outer.inner.deepFunc()
External Modules
Load code from separate files:
// In main.ox - loads utils.ox or utils/mod.ox
external module utils
external module api
fn main() {
utils.doSomething()
api.endpoint()
}
Transpiles to:
mod utils;
mod api;
fn main() {
utils::do_something();
api::endpoint();
}
File Resolution
External modules are resolved as:
utils.ox- Single file moduleutils/mod.ox- Directory module with submodules
Visibility Modifiers
Oxide uses intuitive visibility keywords:
| Oxide | Rust | Visibility |
|---|---|---|
(none) or private | (none) | Module-private |
public | pub | Public everywhere |
internal | pub(crate) | Crate-wide |
protected | pub(super) | Parent module |
Basic Visibility
module helpers {
public fn publicFn(): Int { 42 } // Public everywhere
internal fn crateFn(): Int { 1 } // Crate-wide
protected fn parentFn(): Int { 2 } // Parent module only
private fn privateFn(): Int { 0 } // Module-private (explicit)
fn implicitPrivate(): Int { 0 } // Module-private (default)
}
Transpiles to:
mod helpers {
pub fn public_fn() -> isize { 42 }
pub(crate) fn crate_fn() -> isize { 1 }
pub(super) fn parent_fn() -> isize { 2 }
fn private_fn() -> isize { 0 }
fn implicit_private() -> isize { 0 }
}
Internal (Crate-Wide)
Use internal for items visible throughout the crate but not publicly:
module utils {
internal fn internalHelper(): Int { 42 }
internal struct InternalConfig(
debug: Bool,
maxRetries: Int
)
}
// Accessible from any module in the crate
fn main() {
let result = utils.internalHelper()
}
Protected (Parent Module)
Use protected for items visible only to the parent module:
module parent {
module child {
protected fn childHelper(): Int { 100 }
private fn privateToChild(): Int { 0 }
}
fn useChild(): Int {
child.childHelper() // OK - parent can access
}
}
// parent.child.childHelper() // Error! Not visible outside parent
Re-exports
Re-export items from other modules:
module internal {
public fn helper(): Int { 42 }
}
// Re-export at current level
public import internal.helper
// Re-export from standard library
public import std.collections.HashMap
Transpiles to:
mod internal {
pub fn helper() -> isize { 42 }
}
pub use internal::helper;
pub use std::collections::HashMap;
Import Statements
Import items for easier access using the import keyword with dot-separated paths:
import std.collections.HashMap
import std.io.{Read, Write}
import crate.utils.helper
fn main() {
let map = HashMap.new()
}
Aliased Imports
import std.collections.HashMap as Map
import crate.very_long_module_name.Type as ShortType
Glob Imports
import std.collections.* // Import all public items
Glob-Except Imports
Exclude specific items from a glob import:
import std.prelude.* except (Vec, String) // Import all except Vec and String
Type-Only Imports
Import only for type checking (no runtime effect):
import type serde.Serialize
import type serde.{Deserialize, Serialize}
Constants and Statics
const MAX_SIZE: Int = 1024
const PI: Float64 = 3.14159
static COUNTER: Int = 0
static var MUTABLE_COUNTER: Int = 0
Transpiles to:
const MAX_SIZE: isize = 1024;
const PI: f64 = 3.14159;
static COUNTER: isize = 0;
static mut MUTABLE_COUNTER: isize = 0;
Type Aliases
type Result<T> = std.result.Result<T, String>
type IntList = Vec<Int>
type Handler = fn(Request) -> Response
Project Structure
Typical Oxide project layout:
my-project/
├── Cargo.toml
├── src/
│ ├── main.ox # Binary entry point
│ ├── lib.ox # Library entry point (optional)
│ ├── utils.ox # Single file module
│ └── api/ # Directory module
│ ├── mod.ox # Module root
│ ├── routes.ox # Submodule
│ └── handlers.ox
├── tests/
│ └── integration.ox
└── examples/
└── demo.ox
main.ox
external module utils
external module api
fn main() {
utils.init()
api.start()
}
lib.ox
public external module utils
public external module api
public fn version(): String { "1.0.0" }
api/mod.ox
public external module routes
public external module handlers
public fn start() {
routes.register()
}
Prelude
Oxide automatically imports the stdlib prelude:
// These are automatically available:
// - StringExt, OptionExt, ResultExt
// - Array, Map, IteratorExt
// - abs, min, max, clamp
// - readFile, writeFile, etc.
To disable:
@file:[no_prelude]
// Manual imports required
Migration from Old Syntax
If you have code using the old use keyword with :: separators:
// Old syntax (deprecated, produces error)
use std::collections::HashMap
use std::io::*
use crate::utils::{helper, format}
// New syntax
import std.collections.HashMap
import std.io.*
import crate.utils.{helper, format}
See Also
- Traits - Visibility on traits
- Data Structures - Struct/enum visibility
- Standard Library - Prelude contents