| layout | default |
|---|---|
| title | API Reference |
| parent | Reference |
| nav_order | 2 |
Castella is a reactive GUI framework for Konpeito's JVM backend. It uses JWM + Skija for cross-platform rendering and provides a component model with observable state management.
Every Castella app follows this structure:
class MyApp < Component
def initialize
super
@count = state(0) # reactive state
end
def view
Column(
Text("Hello"),
Button("Click").on_click { @count += 1 }
)
end
end
$theme = theme_tokyo_night
frame = JWMFrame.new("My App", 800, 600)
app = App.new(frame, MyApp.new)
app.runKey concepts:
- Subclass
Componentand overrideview()to return a widget tree. - Call
state(initial_value)to create reactive state. When state changes,view()is re-called automatically. - Set
$themeto a theme object before creating the frame. JWMFramecreates the native window.Appconnects the window to your root component.
DSL alternative:
Instead of Column(...) constructor calls, use lowercase block functions with keyword arguments:
def view
column(padding: 16.0) do
text "Hello", font_size: 24.0
button("Click") { @count += 1 }
end
endKeyword arguments (padding:, font_size:, color:, etc.) configure layout and styling directly. Style objects via the s helper are also supported as the first positional argument.
Stacks children vertically.
# Constructor style
Column(child1, child2, child3)
# DSL style
column(style) { ... }| Method | Description |
|---|---|
.spacing(Float) |
Gap between children in pixels |
.scrollable |
Enable vertical scrolling |
.pin_to_bottom |
Auto-scroll to bottom when content grows |
Stacks children horizontally.
Row(child1, child2, child3)
row(style) { ... }| Method | Description |
|---|---|
.spacing(Float) |
Gap between children in pixels |
.scrollable |
Enable horizontal scrolling |
.pin_to_end |
Auto-scroll to end when content grows |
Wraps a single child with background, border, and padding.
Container(child)
container(style) { ... }| Method | Description |
|---|---|
.bg_color(Integer) |
Background color (ARGB hex) |
.border_color(Integer) |
Border color (ARGB hex) |
.border_radius(Float) |
Corner radius in pixels |
.padding(top, right, bottom, left) |
Inner padding |
Overlay layout — children are stacked at the same position, layered by z-index.
Box(child1, child2)
box(style) { ... }Flexible empty space that expands to fill available room.
Spacer()
spacerUse Spacer() between widgets to push them apart. For fixed spacing, use .fixed_width(w) or .fixed_height(h).
Visual separator line.
Divider()
divider| Method | Description |
|---|---|
.color(Integer) |
Line color (ARGB hex) |
Displays a single line of text.
Text("Hello, world!")
text("Hello, world!", style)| Method | Description |
|---|---|
.font_size(Float) |
Font size in pixels |
.font_family(String) |
Font family name |
.color(Integer) |
Text color (ARGB hex) |
.bold |
Bold weight |
.italic |
Italic style |
.align(Integer) |
Alignment: TEXT_ALIGN_LEFT (0), TEXT_ALIGN_CENTER (1), TEXT_ALIGN_RIGHT (2) |
.kind(Integer) |
Semantic color: KIND_NORMAL (0), KIND_INFO (1), KIND_SUCCESS (2), KIND_WARNING (3), KIND_DANGER (4) |
Displays multi-line text with word wrapping.
MultilineText("Long text content...")
multiline_text("Long text content...", style)| Method | Description |
|---|---|
.font_size(Float) |
Font size |
.font_family(String) |
Font family |
.color(Integer) |
Text color |
.kind(Integer) |
Semantic color |
.padding(Float) |
Inner padding |
.line_spacing(Float) |
Space between lines |
.wrap_text(bool) |
Enable/disable word wrapping |
Renders Markdown-formatted text.
Markdown("# Heading\n\n**Bold** and *italic*")
markdown("# Heading", style)| Method | Description |
|---|---|
.font_size(Float) |
Base font size |
.enable_mermaid(bool) |
Enable Mermaid diagram rendering |
Displays an image from a local file.
ImageWidget("path/to/image.png")
image("path/to/image.png", style)| Method | Description |
|---|---|
.fit(Integer) |
Fit mode: IMAGE_FIT_FILL (0), IMAGE_FIT_CONTAIN (1), IMAGE_FIT_COVER (2) |
Downloads and displays an image from a URL.
NetImage("https://example.com/image.png")
net_image("https://example.com/image.png", style)| Method | Description |
|---|---|
.fit(Integer) |
Fit mode (same as Image) |
.placeholder_color(Integer) |
Color shown while loading |
Clickable button with a text label.
Button("Click me").on_click { puts "clicked" }
button("Click me", style) { puts "clicked" }| Method | Description |
|---|---|
.on_click { } |
Click handler block |
.font_size(Float) |
Label font size |
.kind(Integer) |
Button style: normal, info, success, warning, danger |
.text_color(Integer) |
Label color |
.bg(Integer) |
Background color |
Single-line text input field. Requires an InputState for state management.
state = InputState.new("placeholder text")
Input(state).on_change { puts state.value }
input(state, style)| Method | Description |
|---|---|
.on_change { } |
Called when text changes |
.font_size(Float) |
Font size |
InputState methods:
| Method | Description |
|---|---|
.value |
Current text content |
.set(String) |
Set text programmatically |
.get_cursor |
Current cursor position |
.select_all |
Select all text |
Multi-line text input with cursor, selection, and IME support. Requires a MultilineInputState.
state = MultilineInputState.new("initial text")
MultilineInput(state).on_change { puts state.value }
multiline_input(state, style)| Method | Description |
|---|---|
.on_change { } |
Called when text changes |
.on_key { } |
Called on key events |
.font_size(Float) |
Font size |
.font_family(String) |
Font family |
MultilineInputState methods:
| Method | Description |
|---|---|
.value / .get_text |
Current text content |
.set_text(String) |
Set text programmatically |
.get_lines |
Array of text lines |
.get_row / .get_col |
Cursor position |
.select_all |
Select all text |
Toggleable checkbox with a text label.
Checkbox("Enable feature").checked(true).on_toggle { |checked| puts checked }
checkbox("Enable feature", style)| Method | Description |
|---|---|
.checked(bool) |
Set initial checked state |
.is_checked |
Get current state |
| `.on_toggle { | bool |
.font_size(Float) |
Label font size |
.check_color(Integer) |
Checkmark color |
.text_color(Integer) |
Label color |
ON/OFF toggle switch.
Switch().with_on(true).on_change { |is_on| puts is_on }
switch_toggle(style)| Method | Description |
|---|---|
.with_on(bool) |
Set initial state |
.is_on |
Get current state |
| `.on_change { | bool |
Draggable range input.
Slider(0, 100).with_value(50).on_change { |val| puts val }
slider(0, 100, style)| Method | Description |
|---|---|
.with_value(Integer) |
Set initial value |
.get_value |
Get current value |
.on_change { } |
Called when value changes |
Exclusive selection from a list of options.
RadioButtons(["Option A", "Option B", "Option C"])
.with_selected(0)
.on_change { |index| puts index }
radio_buttons(["Option A", "Option B"], style)| Method | Description |
|---|---|
.with_selected(Integer) |
Set initial selection index |
.get_selected |
Get current selection index |
| `.on_change { | Integer |
Visual progress indicator (0.0 to 1.0).
ProgressBar().with_value(0.75)
progress_bar(style)| Method | Description |
|---|---|
.with_value(Float) |
Set progress (0.0 to 1.0) |
.set_value(Float) |
Update progress |
.get_value |
Get current progress |
.fill_color(Integer) |
Bar fill color |
Tabbed container with header buttons that switch between content panels.
Tabs(
["Tab 1", "Tab 2"],
[content_widget_1, content_widget_2]
)
tabs(["Tab 1", "Tab 2"], [widget1, widget2], style)| Method | Description |
|---|---|
.select_tab(Integer) |
Switch to tab by index |
Sortable, scrollable table with virtual scrolling for large datasets.
DataTable(
["Name", "Age", "City"], # column headers
[150.0, 60.0, 120.0], # column widths
[ # row data
["Alice", "30", "Tokyo"],
["Bob", "25", "Osaka"]
]
)
data_table(columns, widths, rows, style)| Method | Description |
|---|---|
.font_size(Float) |
Body font size |
.header_font_size(Float) |
Header font size |
.set_data(cols, widths, rows) |
Replace all data |
.set_rows(rows) |
Replace row data only |
.selected_row |
Get selected row index |
| `.on_select { | Integer |
| `.on_sort { | col, dir |
Sort directions: DT_SORT_NONE (0), DT_SORT_ASC (1), DT_SORT_DESC (2).
Hierarchical tree view with expand/collapse.
Tree(items)
tree(items, style)| Method | Description |
|---|---|
.font_size(Float) |
Font size |
.indent_width(Float) |
Indentation per level |
.on_select { } |
Called when an item is selected |
.on_expand { } |
Called when a node is expanded |
.on_collapse { } |
Called when a node is collapsed |
Date picker with day, month, and year views.
Calendar(2026, 2, 15) # year, month, day
calendar(style)| Method | Description |
|---|---|
.with_selected(year, month, day) |
Set selected date |
.get_selected_date |
Get [year, month, day] array |
.set_view_mode(Integer) |
CAL_DAYS (0), CAL_MONTHS (1), CAL_YEARS (2) |
| `.on_change { | y, m, d |
Overlay dialog with backdrop.
Modal(content_widget).title("Confirm").dialog_size(400.0, 300.0)
modal(content_widget)| Method | Description |
|---|---|
.title(String) |
Dialog title |
.dialog_size(Float, Float) |
Width and height |
.open_modal |
Show the modal |
.close_modal |
Hide the modal |
.is_open |
Check if modal is visible |
All chart widgets are available through DSL functions.
bar_chart(
["Jan", "Feb", "Mar"], # x-axis labels
[[10.0, 20.0, 15.0], [5.0, 15.0, 25.0]], # data series
["Sales", "Returns"] # legend labels
)line_chart(labels, data_series, legends)area_chart(labels, data_series, legends)stacked_bar_chart(labels, data_series, legends)pie_chart(
["Ruby", "Python", "Go"], # labels
[45.0, 30.0, 25.0] # values
)scatter_chart(
[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], # x data per series
[[10.0, 20.0, 30.0], [15.0, 25.0, 35.0]], # y data per series
["Series A", "Series B"] # legend labels
)gauge_chart(75.0, 0.0, 100.0) # value, min, maxheatmap_chart(
["Mon", "Tue", "Wed"], # x labels
["Morning", "Afternoon"], # y labels
[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]] # data grid
)Styles configure layout and appearance. Create a style with s (DSL helper) or Style.new, then chain methods:
my_style = s.font_size(18.0).bold.color(0xFFC0CAF5).padding(8.0)Styles are composable:
base = s.font_size(14.0).color(0xFFC0CAF5)
header = base + s.bold.font_size(24.0) # combines both| Method | Description |
|---|---|
.width(Float) / .fixed_width(Float) |
Fixed width in pixels |
.height(Float) / .fixed_height(Float) |
Fixed height in pixels |
.size(Float, Float) |
Fixed width and height |
.expanding |
Expand to fill available space (both axes) |
.expanding_width |
Expand horizontally only |
.expanding_height |
Expand vertically only |
.flex(Integer) |
Flex factor for proportional sizing |
.fit_content |
Size to content |
.padding(Float) |
Uniform padding on all sides |
.spacing(Float) |
Gap between children (Column/Row) |
| Method | Description |
|---|---|
.bg_color(Integer) |
Background color (ARGB hex) |
.border_color(Integer) |
Border color (ARGB hex) |
.border_radius(Float) |
Corner radius |
| Method | Description |
|---|---|
.font_size(Float) |
Font size in pixels |
.font_family(String) |
Font family name |
.color(Integer) / .text_color(Integer) |
Text color (ARGB hex) |
.bold |
Bold weight |
.italic |
Italic style |
.align(Integer) |
Text alignment (0=left, 1=center, 2=right) |
.kind(Integer) |
Semantic color (0=normal, 1=info, 2=success, 3=warning, 4=danger) |
| Method | Description |
|---|---|
.scrollable |
Enable scrolling |
.pin_to_bottom |
Auto-scroll to bottom (Column) |
.pin_to_end |
Auto-scroll to end (Row) |
Colors use ARGB hex format: 0xAARRGGBB
0xFFFFFFFF # white, fully opaque
0xFF000000 # black, fully opaque
0x80FF0000 # red, 50% transparent
0xFFC0CAF5 # Tokyo Night text colorObservable value holder. When mutated, all observing components re-render.
@count = state(0) # create in Component#initialize
@count.value # read: 0
@count.set(5) # write: triggers re-render
@count += 1 # shorthand for set(value + 1)
@count -= 1 # shorthand for set(value - 1)Observable array for dynamic lists.
@items = ListState.new(["Apple", "Banana"])
@items.length # 2
@items[0] # "Apple"
@items[1] = "Cherry" # replace element
@items.push("Date") # append
@items.pop # remove last
@items.delete_at(0) # remove at index
@items.clear # remove all
@items.set(["X", "Y"]) # replace entire list
@items.each { |item| ... } # iterateObservable scroll position.
@scroll = ScrollState.new
@scroll.x # horizontal offset
@scroll.y # vertical offset
@scroll.set_x(100.0)
@scroll.set_y(200.0)
@scroll.set(100.0, 200.0)State for single-line text input widgets. See Input widget for details.
@input = InputState.new("placeholder")
@input.value # current text
@input.set("new text") # set text programmaticallyState for multi-line text input widgets. See MultilineInput widget for details.
@editor = MultilineInputState.new("initial text")
@editor.value # current text
@editor.set_text("new") # set text programmaticallySet $theme before creating the frame:
$theme = theme_tokyo_night # dark theme (default)
$theme = theme_light # light theme
$theme = theme_nord # Nord palette
$theme = theme_dracula # Dracula palette
$theme = theme_catppuccin # Catppuccin paletteUse theme colors in styles for consistent theming:
text "Hello", color: $theme.text_primary
container(bg_color: $theme.bg_secondary) { ... }
button("OK", kind: KIND_SUCCESS)| Property | Description |
|---|---|
.bg_canvas |
Main canvas background |
.bg_primary |
Primary surface background |
.bg_secondary |
Secondary surface background |
.bg_overlay |
Overlay/modal background |
.text_primary |
Primary text color |
.text_secondary |
Secondary/muted text color |
.accent |
Accent/highlight color |
.info |
Info semantic color |
.error |
Error semantic color |
.success |
Success semantic color |
.warning |
Warning semantic color |
.border |
Default border color |
.border_focus |
Focused element border color |
.font_family |
Default font family name |
.font_size_sm / .font_size_md / .font_size_lg / .font_size_xl |
Font size presets |
.spacing_xs / .spacing_sm / .spacing_md / .spacing_lg |
Spacing presets |
.border_radius |
Default corner radius |
.scrollbar_bg / .scrollbar_fg |
Scrollbar colors |
.bg_selected |
Selected item background |
Widgets support event callbacks via chainable methods:
Button("Click").on_click { puts "clicked" }
Checkbox("Toggle").on_toggle { |checked| puts checked }
Slider(0, 100).on_change { |value| puts value }
Input(state).on_change { puts state.value }For low-level event handling, override methods on your Component or custom Widget subclass:
| Method | Description |
|---|---|
mouse_down(MouseEvent) |
Mouse button pressed |
mouse_up(MouseEvent) |
Mouse button released |
mouse_drag(MouseEvent) |
Mouse moved while button held |
mouse_over |
Mouse entered widget bounds |
mouse_out |
Mouse left widget bounds |
mouse_wheel(WheelEvent) |
Scroll wheel event |
input_char(String) |
Character typed |
input_key(key_code, modifiers) |
Key pressed |
focused |
Widget received focus |
unfocused |
Widget lost focus |
All widgets inherit these methods from the base Widget class:
| Method | Description |
|---|---|
.fixed_width(Float) |
Set fixed width |
.fixed_height(Float) |
Set fixed height |
.fixed_size(Float, Float) |
Set fixed width and height |
.fit_content |
Size to content |
.flex(Integer) |
Flex factor |
.padding(top, right, bottom, left) |
Inner padding |
.z_index(Integer) |
Z-order for overlapping widgets |
.tab_index(Integer) |
Tab navigation order |
.focusable(bool) |
Whether widget can receive focus |
These types provide high-performance data handling by bypassing Ruby's object model. They are available when compiling with the LLVM/native backend.
Contiguous unboxed array. Element types: Integer, Float, or NativeClass.
Local NativeArray — dynamically sized, allocated within a function:
class NativeArray[T]
def self.new: (Integer size) -> NativeArray[T]
def []: (Integer index) -> T
def []=: (Integer index, T value) -> T
def length: () -> Integer
endarr = NativeArray.new(1000)
arr[0] = 3.14
arr[0] # => 3.14 (unboxed double)
arr.length # => 1000Module NativeArray — fixed-size, global arrays shared across functions (LLVM/mruby backends):
# Separate RBS file, or inline with rbs_inline
module GameState
@positions: NativeArray[Integer, 100]
@velocities: NativeArray[Float, 100]
end# rbs_inline: enabled
# @rbs module GameState
# @rbs @positions: NativeArray[Integer, 100]
# @rbs @velocities: NativeArray[Float, 100]
# @rbs end
def init
i = 0
while i < 100
GameState.positions[i] = i * 10
GameState.velocities[i] = 0.0
i = i + 1
end
end
def update
GameState.positions[0] = GameState.positions[0] + 1
endModule NativeArray compiles to LLVM global arrays (internal global [N x T] zeroinitializer). No C wrapper file is needed — the compiler generates the global storage directly from the RBS declaration. All functions in the compilation unit can read and write these arrays.
Supports negative indexing: arr[-1] is the last element.
Enumerable methods: each, map, select, reject, reduce, find, any?, all?, none?, sum, min, max.
Open-addressing hash map with linear probing.
Key types: String, Symbol, Integer
Value types: Integer, Float, Bool, String, Object, Array, Hash, NativeClass
class NativeHash[K, V]
def self.new: () -> NativeHash[K, V]
def []: (K key) -> V
def []=: (K key, V value) -> V
def size: () -> Integer
def has_key?: (K key) -> bool
def delete: (K key) -> V
def keys: () -> Array
def values: () -> Array
def clear: () -> NativeHash[K, V]
endh = NativeHash.new
h[1] = 100
h[2] = 200
h.has_key?(1) # => true
h.size # => 2
h.delete(1)Auto-resizes at 75% load factor.
Classes with RBS field definitions are automatically compiled as native structs (no annotation needed).
Supported field types:
- Unboxed:
Integer(i64),Float(double),Bool(i8) - VALUE (GC-managed):
String,Array,Hash,Object
class Point
@x: Float
@y: Float
def self.new: () -> Point
def x: () -> Float
def x=: (Float value) -> Float
def y: () -> Float
def y=: (Float value) -> Float
endp = Point.new
p.x = 3.0
p.y = 4.0
p.x * p.x + p.y * p.y # => 25.0 (unboxed arithmetic)Fixed-size array allocated on the stack (no heap allocation, no GC pressure).
class StaticArray4Float
def self.new: () -> StaticArray4Float
def self.new: (Float value) -> StaticArray4Float
def []: (Integer index) -> Float
def []=: (Integer index, Float value) -> Float
def size: () -> Integer
endName encodes type and size: StaticArray4Float, StaticArray16Int, etc.
arr = StaticArray4Float.new(0.0)
arr[0] = 1.0
arr[1] = 2.0
arr.size # => 4 (compile-time constant)Bounds-checked pointer view with sub-slicing (zero-copy).
class SliceInt64
def self.new: (Integer size) -> SliceInt64
def self.empty: () -> SliceInt64
def []: (Integer index) -> Integer
def []=: (Integer index, Integer value) -> Integer
def []: (Integer start, Integer count) -> SliceInt64
def size: () -> Integer
def copy_from: (SliceInt64 source) -> SliceInt64
def fill: (Integer value) -> SliceInt64
ends = SliceInt64.new(10)
s[3] = 42
window = s[3, 4] # zero-copy sub-slice of 4 elements starting at index 3
window[0] # => 42 (same memory as s[3])Buffer types for I/O operations.
ByteBuffer — growable byte array:
buf = ByteBuffer.new(1024)
buf << 65 # append byte
buf.write("hello") # append string bytes
buf.index_of(104) # find byte (memchr)
buf.to_s # convert to Ruby StringStringBuffer — efficient string concatenation:
buf = StringBuffer.new(256)
buf << "Hello, "
buf << "world!"
buf.to_s # => "Hello, world!"ByteSlice — zero-copy view into a ByteBuffer:
slice = buf.slice(0, 5)
slice[0] # first byte
slice.length
slice.to_s # => "Hello"UTF-8 string with byte-level and character-level operations.
ns = NativeString.from("Hello, world!")
ns.byte_length # => 13
ns.byte_at(0) # => 72 (ASCII 'H')
ns.byte_index_of(32) # => 5 (first space)
ns.byte_slice(0, 5).to_s # => "Hello" (zero-copy)
ns.char_length # => 13
ns.char_at(0) # => "H"
ns.ascii_only? # => true
ns.starts_with?("Hello") # => true
ns.to_s # => Ruby StringValue types are passed by value (copied) rather than by reference. Best for small structs (2-4 fields).
# @struct
class Point
@x: Float
@y: Float
def self.new: () -> Point
def x: () -> Float
def y: () -> Float
endConstraints: Only primitive fields (Integer, Float, Bool). No VALUE fields (String, Array, etc.). Maximum 128 bytes.
JSON parsing and generation powered by yyjson.
# Parse JSON string
data = KonpeitoJSON.parse('{"name": "Alice", "age": 30}')
# Generate JSON string
json = KonpeitoJSON.generate(data)
# Pretty-print with indentation
json = KonpeitoJSON.generate_pretty(data, 2)
# Parse with options
data = KonpeitoJSON.parse(text, KonpeitoJSON::ALLOW_COMMENTS | KonpeitoJSON::ALLOW_TRAILING_COMMAS)| Method | Description |
|---|---|
parse(String) -> untyped |
Parse JSON string |
parse(String, Integer) -> untyped |
Parse with flags |
generate(untyped) -> String |
Serialize to compact JSON |
generate_pretty(untyped, Integer) -> String |
Serialize with indentation |
Parse flags:
| Constant | Description |
|---|---|
ALLOW_COMMENTS |
Allow // and /* */ comments |
ALLOW_TRAILING_COMMAS |
Allow trailing commas in arrays/objects |
ALLOW_INF_NAN |
Allow Infinity and NaN values |
HTTP client powered by libcurl.
# Simple GET (returns body string)
body = KonpeitoHTTP.get("https://example.com")
# Simple POST
body = KonpeitoHTTP.post("https://example.com/api", '{"key": "value"}')
# GET with full response
resp = KonpeitoHTTP.get_response("https://example.com")
resp[:status] # => 200
resp[:body] # => "..."
resp[:headers] # => { "content-type" => "text/html", ... }
# POST with full response and content type
resp = KonpeitoHTTP.post_response("https://example.com/api", body, "application/json")
# Custom request
resp = KonpeitoHTTP.request("PUT", "https://example.com/api/1", body, {
"Authorization" => "Bearer token",
"Content-Type" => "application/json"
})| Method | Description |
|---|---|
get(String) -> String |
GET request, returns body |
post(String, String) -> String |
POST request, returns body |
get_response(String) -> Hash |
GET with status/headers/body |
post_response(String, String, String?) -> Hash |
POST with response details |
request(String, String, String?, Hash?) -> Hash |
Custom method/headers |
Features: automatic redirect following, 30-second timeout. Falls back to Ruby's net/http if libcurl is unavailable.
Cryptographic operations powered by OpenSSL.
# Hash functions (hex output)
KonpeitoCrypto.sha256("hello") # => "2cf24dba..."
KonpeitoCrypto.sha512("hello") # => "9b71d224..."
# Binary output
KonpeitoCrypto.sha256_binary("hello") # => binary string
# HMAC
KonpeitoCrypto.hmac_sha256("secret", "message")
KonpeitoCrypto.hmac_sha512("secret", "message")
# Random bytes
KonpeitoCrypto.random_bytes(32) # => 32 random bytes
KonpeitoCrypto.random_hex(16) # => 32-char hex string
# Timing-safe comparison
KonpeitoCrypto.secure_compare(a, b) # => true/false| Method | Description |
|---|---|
sha256(String) -> String |
SHA-256 hash (hex) |
sha512(String) -> String |
SHA-512 hash (hex) |
sha256_binary(String) -> String |
SHA-256 hash (binary) |
sha512_binary(String) -> String |
SHA-512 hash (binary) |
hmac_sha256(String, String) -> String |
HMAC-SHA256 (hex) |
hmac_sha512(String, String) -> String |
HMAC-SHA512 (hex) |
hmac_sha256_binary(String, String) -> String |
HMAC-SHA256 (binary) |
hmac_sha512_binary(String, String) -> String |
HMAC-SHA512 (binary) |
random_bytes(Integer) -> String |
Cryptographic random bytes |
random_hex(Integer) -> String |
Cryptographic random hex string |
secure_compare(String, String) -> bool |
Timing-safe string comparison |
Falls back to Ruby's OpenSSL gem if the native library is unavailable.
Compression and decompression powered by zlib.
# Gzip (RFC 1952)
compressed = KonpeitoCompression.gzip("hello world")
original = KonpeitoCompression.gunzip(compressed)
# Raw deflate (RFC 1951)
compressed = KonpeitoCompression.deflate("hello world")
compressed = KonpeitoCompression.deflate("hello world", KonpeitoCompression::BEST_COMPRESSION)
original = KonpeitoCompression.inflate(compressed)
# Zlib format (RFC 1950)
compressed = KonpeitoCompression.zlib_compress("hello world")
original = KonpeitoCompression.zlib_decompress(compressed)
original = KonpeitoCompression.zlib_decompress(compressed, 1048576) # max output size| Method | Description |
|---|---|
gzip(String) -> String |
Gzip compress |
gunzip(String) -> String |
Gzip decompress |
deflate(String, Integer?) -> String |
Raw deflate compress |
inflate(String) -> String |
Raw deflate decompress |
zlib_compress(String) -> String |
Zlib format compress |
zlib_decompress(String, Integer?) -> String |
Zlib format decompress |
Compression level constants:
| Constant | Value | Description |
|---|---|---|
BEST_SPEED |
1 | Fastest compression |
BEST_COMPRESSION |
9 | Smallest output |
DEFAULT_COMPRESSION |
-1 | Default balance |
Falls back to Ruby's Zlib module if the native library is unavailable.
Konpeito uses RBS annotations (%a{...}) to control native code generation.
| Annotation | Target | Description |
|---|---|---|
%a{native} |
class | Compile as native struct (default for classes with RBS fields) |
%a{native: vtable} |
class | Native struct with vtable for dynamic dispatch |
%a{boxed} |
class | Use Ruby VALUE type (for CRuby interop) |
%a{struct} |
class | Value type (stack-allocated, passed by value) |
%a{extern} |
class | Wrapper for external C struct |
%a{simd} |
class | SIMD vectorization (all Float fields, 2/3/4/8/16 fields) |
%a{ffi: "lib"} |
module/class | Link external C library |
%a{cfunc} |
method | Call C function directly (method name = function name) |
%a{cfunc: "name"} |
method | Call C function directly (explicit function name) |
%a{jvm_static} |
method | Generate as JVM static method |
%a{ffi: "libm"}
module MathLib
%a{cfunc}
def self.sin: (Float) -> Float
%a{cfunc: "sqrt"}
def self.square_root: (Float) -> Float
endmodule MathLib
def self.sin(x) = nil
def self.square_root(x) = nil
end
MathLib.sin(3.14159 / 2) # => 1.0 (direct C call)
MathLib.square_root(16.0) # => 4.0 (direct C call)Raylib is a graphics stdlib for the mruby backend, providing zero-boilerplate game development. Simply reference module Raylib in your code and the compiler auto-detects the stdlib — no manual RBS or C file setup needed.
module Raylib
end
def main
Raylib.init_window(800, 600, "My Game")
Raylib.set_target_fps(60)
while Raylib.window_should_close == 0
Raylib.begin_drawing
Raylib.clear_background(Raylib.color_raywhite)
Raylib.draw_text("Hello, Raylib!", 200, 260, 40, Raylib.color_darkgray)
Raylib.end_drawing
end
Raylib.close_window
end
mainkonpeito run --target mruby game.rbNote: Boolean-returning functions (e.g., key_down?, window_should_close) return Integer (0 or 1), not Ruby true/false. Use != 0 for conditionals.
| Method | Signature | Description |
|---|---|---|
init_window |
(Integer w, Integer h, String title) -> void |
Create window |
close_window |
() -> void |
Close window |
window_should_close |
() -> Integer |
Returns 1 if close requested |
set_target_fps |
(Integer fps) -> void |
Set target framerate |
get_frame_time |
() -> Float |
Delta time since last frame |
get_time |
() -> Float |
Elapsed time since init |
get_screen_width |
() -> Integer |
Window width |
get_screen_height |
() -> Integer |
Window height |
set_window_title |
(String title) -> void |
Update window title |
set_window_size |
(Integer w, Integer h) -> void |
Resize window |
window_focused? |
() -> Integer |
1 if window has focus |
window_resized? |
() -> Integer |
1 if window was resized |
toggle_fullscreen |
() -> void |
Toggle fullscreen mode |
get_fps |
() -> Integer |
Current FPS |
| Method | Signature | Description |
|---|---|---|
begin_drawing |
() -> void |
Start drawing frame |
end_drawing |
() -> void |
End drawing frame (swap buffers) |
clear_background |
(Integer color) -> void |
Clear with color |
draw_rectangle |
(Integer x, y, w, h, Integer color) -> void |
Filled rectangle |
draw_rectangle_lines |
(Integer x, y, w, h, Integer color) -> void |
Rectangle outline |
draw_circle |
(Integer cx, cy, Float radius, Integer color) -> void |
Filled circle |
draw_circle_lines |
(Integer cx, cy, Float radius, Integer color) -> void |
Circle outline |
draw_line |
(Integer x1, y1, x2, y2, Integer color) -> void |
Line |
draw_line_ex |
(Float x1, y1, x2, y2, Float thick, Integer color) -> void |
Thick line |
draw_triangle |
(Float x1, y1, x2, y2, x3, y3, Integer color) -> void |
Filled triangle |
draw_pixel |
(Integer x, y, Integer color) -> void |
Single pixel |
| Method | Signature | Description |
|---|---|---|
draw_text |
(String text, Integer x, y, size, Integer color) -> void |
Draw text |
measure_text |
(String text, Integer size) -> Integer |
Text width in pixels |
| Method | Signature | Description |
|---|---|---|
key_down? |
(Integer key) -> Integer |
1 if key is held down |
key_pressed? |
(Integer key) -> Integer |
1 if key was pressed this frame |
key_released? |
(Integer key) -> Integer |
1 if key was released this frame |
key_up? |
(Integer key) -> Integer |
1 if key is not pressed |
get_key_pressed |
() -> Integer |
Last key pressed (0 if none) |
get_char_pressed |
() -> Integer |
Last char pressed (0 if none) |
| Method | Signature | Description |
|---|---|---|
get_mouse_x |
() -> Integer |
Mouse X position |
get_mouse_y |
() -> Integer |
Mouse Y position |
mouse_button_pressed? |
(Integer btn) -> Integer |
1 if button pressed this frame |
mouse_button_down? |
(Integer btn) -> Integer |
1 if button is held |
mouse_button_released? |
(Integer btn) -> Integer |
1 if button released this frame |
get_mouse_wheel_move |
() -> Float |
Mouse wheel movement |
27 built-in color constants, plus custom color creation:
| Method | Description |
|---|---|
color_white, color_black |
Basic colors |
color_red, color_green, color_blue |
Primary colors |
color_yellow, color_orange, color_pink, color_purple |
Secondary colors |
color_darkgray, color_lightgray, color_gray, color_raywhite |
Grays |
color_darkblue, color_skyblue, color_lime, color_darkgreen |
Extended colors |
color_darkpurple, color_violet, color_brown, color_darkbrown |
Extended colors |
color_beige, color_maroon, color_gold, color_magenta, color_blank |
More colors |
color_new(r, g, b, a) -> Integer |
Custom RGBA color |
color_alpha(color, alpha) -> Integer |
Modify alpha channel |
Colors are packed RGBA integers. Use color_new(255, 0, 0, 255) for red with full opacity.
| Method | Value | Method | Value |
|---|---|---|---|
key_right |
Right arrow | key_left |
Left arrow |
key_up |
Up arrow | key_down |
Down arrow |
key_space |
Space | key_enter |
Enter/Return |
key_escape |
Escape | key_a .. key_z |
Letter keys |
key_zero .. key_nine |
Number keys |
| Method | Description |
|---|---|
mouse_left |
Left mouse button |
mouse_right |
Right mouse button |
mouse_middle |
Middle mouse button |
| Method | Signature | Description |
|---|---|---|
get_random_value |
(Integer min, Integer max) -> Integer |
Random integer in range |
Clay is a Flexbox-style UI layout library for the mruby backend. It computes layouts from a tree of containers and outputs renderer-agnostic draw commands. Konpeito integrates the official raylib renderer for one-call rendering.
Reference module Clay in your code for auto-detection (same as Raylib).
| Method | Signature | Description |
|---|---|---|
init |
(Float w, Float h) -> void |
Initialize Clay arena and context |
destroy |
() -> void |
Free Clay arena memory |
begin_layout |
() -> void |
Begin a new layout frame |
end_layout |
() -> Integer |
End layout, returns command count |
set_dimensions |
(Float w, Float h) -> void |
Update layout dimensions (on resize) |
| Method | Signature | Description |
|---|---|---|
set_pointer |
(Float x, Float y, Integer down) -> void |
Update pointer position and state |
pointer_over |
(String id) -> Integer |
Check if pointer is over element (1=yes) |
pointer_over_i |
(String id, Integer index) -> Integer |
Check pointer over indexed element |
| Method | Signature | Description |
|---|---|---|
open |
(String id) -> void |
Open a new element container |
open_i |
(String id, Integer index) -> void |
Open element with index (for loops) |
close |
() -> void |
Close current element |
Clay.layout(dir, pl, pr, pt, pb, gap, swt, swv, sht, shv, ax, ay)
| Parameter | Type | Description |
|---|---|---|
dir |
Integer | Direction: 0=LEFT_TO_RIGHT, 1=TOP_TO_BOTTOM |
pl, pr, pt, pb |
Integer | Padding: left, right, top, bottom |
gap |
Integer | Gap between children (pixels) |
swt |
Integer | Width sizing type: 0=FIT, 1=GROW, 2=FIXED, 3=PERCENT |
swv |
Float | Width sizing value (for FIXED/PERCENT) |
sht |
Integer | Height sizing type: 0=FIT, 1=GROW, 2=FIXED, 3=PERCENT |
shv |
Float | Height sizing value (for FIXED/PERCENT) |
ax |
Integer | Horizontal alignment: 0=LEFT, 1=RIGHT, 2=CENTER |
ay |
Integer | Vertical alignment: 0=TOP, 1=BOTTOM, 2=CENTER |
| Method | Signature | Description |
|---|---|---|
bg |
(Float r, Float g, Float b, Float a, Float corner_radius) -> void |
Background color (0-255) + corner radius |
border |
(Float r, Float g, Float b, Float a, Integer top, Integer right, Integer bottom, Integer left, Float corner_radius) -> void |
Border with per-side widths |
scroll |
(Integer horizontal, Integer vertical) -> void |
Enable scrolling (1=enabled) |
floating |
(Float ox, Float oy, Integer z, Integer att_elem, Integer att_parent) -> void |
Floating element with offset and z-index |
| Method | Signature | Description |
|---|---|---|
text |
(String text, Integer font_id, Integer font_size, Float r, Float g, Float b, Float a, Integer wrap) -> void |
Add text element |
set_measure_text_raylib |
() -> void |
Register raylib text measurement callback |
load_font |
(String path, Integer size) -> Integer |
Load TTF font, returns font_id |
| Method | Signature | Description |
|---|---|---|
render_raylib |
() -> void |
Render all layout commands via raylib |
update_scroll |
(Float dx, Float dy, Float dt) -> void |
Update scroll containers |
| Method | Returns | Description |
|---|---|---|
sizing_fit |
0 | FIT sizing — shrink to content |
sizing_grow |
1 | GROW sizing — expand to fill |
sizing_fixed |
2 | FIXED sizing — exact pixel value |
sizing_percent |
3 | PERCENT sizing — percentage of parent |
left_to_right |
0 | Horizontal layout direction |
top_to_bottom |
1 | Vertical layout direction |