media: Update to zig 0.16.0, harden tests and add test build step
This commit is contained in:
@@ -1,15 +1,23 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
const vm_dep = b.dependency("vecmath", .{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const vm_module = vm_dep.module("vecmath");
|
|
||||||
|
|
||||||
const root_module = b.addModule("media", .{
|
const vm_dep = b.dependency("vecmath", .{
|
||||||
|
.target = target,
|
||||||
|
});
|
||||||
|
const vm_mod = vm_dep.module("vecmath");
|
||||||
|
|
||||||
|
const mod = b.addModule("media", .{
|
||||||
.root_source_file = b.path("src/root.zig"),
|
.root_source_file = b.path("src/root.zig"),
|
||||||
|
.target = target,
|
||||||
.link_libc = true,
|
.link_libc = true,
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "vecmath", .module = vm_mod },
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
root_module.addCSourceFile(.{
|
mod.addCSourceFile(.{
|
||||||
.file = b.path("src/stbi/stb_image.c"),
|
.file = b.path("src/stbi/stb_image.c"),
|
||||||
.flags = &.{
|
.flags = &.{
|
||||||
"-std=c17",
|
"-std=c17",
|
||||||
@@ -19,5 +27,12 @@ pub fn build(b: *std.Build) void {
|
|||||||
.language = .c,
|
.language = .c,
|
||||||
});
|
});
|
||||||
|
|
||||||
root_module.addImport("vecmath", vm_module);
|
const mod_tests = b.addTest(.{
|
||||||
|
.root_module = mod,
|
||||||
|
});
|
||||||
|
|
||||||
|
const run_mod_tests = b.addRunArtifact(mod_tests);
|
||||||
|
|
||||||
|
const test_step = b.step("test", "Run tests");
|
||||||
|
test_step.dependOn(&run_mod_tests.step);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.{
|
.{
|
||||||
.name = .media,
|
.name = .media,
|
||||||
.version = "0.0.0",
|
.version = "0.0.0",
|
||||||
.minimum_zig_version = "0.15.2",
|
.minimum_zig_version = "0.16.0",
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"src",
|
"src",
|
||||||
"build.zig",
|
"build.zig",
|
||||||
|
|||||||
@@ -19,3 +19,7 @@ media_type: []const u8,
|
|||||||
/// to contain the entire file, only its beginning. The caller asserts that
|
/// to contain the entire file, only its beginning. The caller asserts that
|
||||||
/// `buffer` is at least `magic_length` bytes long.
|
/// `buffer` is at least `magic_length` bytes long.
|
||||||
isFormat: *const fn (buffer: []const u8) bool,
|
isFormat: *const fn (buffer: []const u8) bool,
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,14 +9,26 @@ pub const Static = struct {
|
|||||||
const sample_rate: f64 = @floatFromInt(self.sample_rate);
|
const sample_rate: f64 = @floatFromInt(self.sample_rate);
|
||||||
return @floatCast(samples / sample_rate);
|
return @floatCast(samples / sample_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Sample = extern struct {
|
pub const Sample = extern struct {
|
||||||
left: i16,
|
left: i16,
|
||||||
right: i16,
|
right: i16,
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Stream = struct {
|
pub const Stream = struct {
|
||||||
source: *std.Io.Reader,
|
source: *std.Io.Reader,
|
||||||
sample_rate: u32,
|
sample_rate: u32,
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,11 +19,15 @@ pub fn Static(comptime W: u32, comptime H: u32) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill(self: *@This(), color: vm.Color) void {
|
pub fn fill(self: *@This(), color: vm.Color) void {
|
||||||
@memset(self.data, color);
|
@memset(&self.data, color);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "Static - refAllDecls" {
|
||||||
|
std.testing.refAllDecls(Static(16, 16));
|
||||||
|
}
|
||||||
|
|
||||||
pub const Dynamic = struct {
|
pub const Dynamic = struct {
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
@@ -65,6 +69,10 @@ pub const Dynamic = struct {
|
|||||||
pub fn fill(self: *@This(), color: vm.Color) void {
|
pub fn fill(self: *@This(), color: vm.Color) void {
|
||||||
@memset(self.data[0 .. self.width * self.height], color);
|
@memset(self.data[0 .. self.width * self.height], color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Hdr = struct {
|
pub const Hdr = struct {
|
||||||
@@ -108,4 +116,8 @@ pub const Hdr = struct {
|
|||||||
pub fn fill(self: *@This(), color: vm.ColorHdr) void {
|
pub fn fill(self: *@This(), color: vm.ColorHdr) void {
|
||||||
@memset(self.data[0 .. self.width * self.height], color);
|
@memset(self.data[0 .. self.width * self.height], color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ const Info = union(enum) {
|
|||||||
pub fn makeFull(full: Header) Info {
|
pub fn makeFull(full: Header) Info {
|
||||||
return .{ .full = full };
|
return .{ .full = full };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Header = struct {
|
const Header = struct {
|
||||||
@@ -107,6 +111,10 @@ const Marker = enum(u8) {
|
|||||||
self == .EOI or
|
self == .EOI or
|
||||||
self == .TEM;
|
self == .TEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The caller asserts that the buffer is at least `format.magic_length` bytes
|
/// The caller asserts that the buffer is at least `format.magic_length` bytes
|
||||||
@@ -137,3 +145,7 @@ pub fn info(buffer: []const u8) ?Info {
|
|||||||
|
|
||||||
@panic("TODO");
|
@panic("TODO");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,3 +35,7 @@ pub fn info(buffer: []const u8) ?Header {
|
|||||||
|
|
||||||
@panic("TODO");
|
@panic("TODO");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ pub const Header = struct {
|
|||||||
filter_method: FilterMethod,
|
filter_method: FilterMethod,
|
||||||
interlace_method: InterlaceMethod,
|
interlace_method: InterlaceMethod,
|
||||||
|
|
||||||
pub fn decode(chunk: Chunk) Header {
|
pub fn decode(chunk: Chunk) !Header {
|
||||||
std.debug.assert(chunk.chunk_type == .IHDR);
|
std.debug.assert(chunk.chunk_type == .IHDR);
|
||||||
|
|
||||||
if (chunk.data.len != 13) return error.InvalidPng;
|
if (chunk.data.len != 13) return error.InvalidPng;
|
||||||
@@ -79,6 +79,10 @@ pub const Header = struct {
|
|||||||
.interlace_method = @enumFromInt(interlace_method),
|
.interlace_method = @enumFromInt(interlace_method),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const BitDepth = enum(u8) {
|
pub const BitDepth = enum(u8) {
|
||||||
@@ -89,7 +93,11 @@ pub const BitDepth = enum(u8) {
|
|||||||
@"16" = 16,
|
@"16" = 16,
|
||||||
|
|
||||||
pub fn range(self: BitDepth) usize {
|
pub fn range(self: BitDepth) usize {
|
||||||
return @as(usize, 2) << @intFromEnum(@intFromEnum(self));
|
return @as(usize, 2) << @intCast(@intFromEnum(self));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,6 +119,10 @@ pub const ColorType = enum(u8) {
|
|||||||
pub fn alphaChannelUsed(self: ColorType) bool {
|
pub fn alphaChannelUsed(self: ColorType) bool {
|
||||||
return @intFromEnum(self) & 0b0000_0100 != 0;
|
return @intFromEnum(self) & 0b0000_0100 != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CompressionMethod = enum(u8) {
|
pub const CompressionMethod = enum(u8) {
|
||||||
@@ -156,6 +168,10 @@ pub const Palette = struct {
|
|||||||
.entries = entries,
|
.entries = entries,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- tRNS --------------------------------------------------------------------
|
// --- tRNS --------------------------------------------------------------------
|
||||||
@@ -209,6 +225,10 @@ pub const Transparency = union(enum) {
|
|||||||
.rgba => error.InvalidPng,
|
.rgba => error.InvalidPng,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const TransparencyPalette = struct {
|
const TransparencyPalette = struct {
|
||||||
@@ -218,6 +238,10 @@ const TransparencyPalette = struct {
|
|||||||
pub fn asSlice(self: *const TransparencyPalette) []const u8 {
|
pub fn asSlice(self: *const TransparencyPalette) []const u8 {
|
||||||
return self.entries[0..self.len];
|
return self.entries[0..self.len];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- gAMA --------------------------------------------------------------------
|
// --- gAMA --------------------------------------------------------------------
|
||||||
@@ -245,6 +269,10 @@ const Gamma = struct {
|
|||||||
const gamma = std.mem.readInt(u32, chunk.data[0..4], .big);
|
const gamma = std.mem.readInt(u32, chunk.data[0..4], .big);
|
||||||
return .{ .gamma = gamma };
|
return .{ .gamma = gamma };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- cHRM --------------------------------------------------------------------
|
// --- cHRM --------------------------------------------------------------------
|
||||||
@@ -274,6 +302,10 @@ const Chromaticities = struct {
|
|||||||
.blue_y = std.mem.readInt(u32, chunk.data[28..32], .big),
|
.blue_y = std.mem.readInt(u32, chunk.data[28..32], .big),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- sRGB --------------------------------------------------------------------
|
// --- sRGB --------------------------------------------------------------------
|
||||||
@@ -301,6 +333,10 @@ const RenderingIntent = enum(u8) {
|
|||||||
if (rendering_intent > 3) return error.InvalidPng;
|
if (rendering_intent > 3) return error.InvalidPng;
|
||||||
return @enumFromInt(rendering_intent);
|
return @enumFromInt(rendering_intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- pHYs --------------------------------------------------------------------
|
// --- pHYs --------------------------------------------------------------------
|
||||||
@@ -310,7 +346,7 @@ pub const PhysicalPixelDimensions = struct {
|
|||||||
pixels_per_unit_y: u32,
|
pixels_per_unit_y: u32,
|
||||||
unit: PhysicalUnit,
|
unit: PhysicalUnit,
|
||||||
|
|
||||||
pub fn decode(chunk: Chunk) PhysicalPixelDimensions {
|
pub fn decode(chunk: Chunk) !PhysicalPixelDimensions {
|
||||||
std.debug.assert(chunk.chunk_type == .pHYs);
|
std.debug.assert(chunk.chunk_type == .pHYs);
|
||||||
|
|
||||||
if (chunk.data.len != 9) return error.InvalidPng;
|
if (chunk.data.len != 9) return error.InvalidPng;
|
||||||
@@ -328,6 +364,10 @@ pub const PhysicalPixelDimensions = struct {
|
|||||||
.unit = @enumFromInt(unit),
|
.unit = @enumFromInt(unit),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PhysicalUnit = enum(u8) {
|
pub const PhysicalUnit = enum(u8) {
|
||||||
@@ -381,41 +421,61 @@ pub const LastModificationTime = struct {
|
|||||||
.second = second,
|
.second = second,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
pub const ChunkType = enum(u32) {
|
pub const ChunkType = enum(u32) {
|
||||||
IHDR = @bitCast("IHDR".*),
|
IHDR = fromName("IHDR"),
|
||||||
PLTE = @bitCast("PLTE".*),
|
PLTE = fromName("PLTE"),
|
||||||
IDAT = @bitCast("IDAT".*),
|
IDAT = fromName("IDAT"),
|
||||||
IEND = @bitCast("IEND".*),
|
IEND = fromName("IEND"),
|
||||||
tRNS = @bitCast("tRNS".*),
|
tRNS = fromName("tRNS"),
|
||||||
gAMA = @bitCast("gAMA".*),
|
gAMA = fromName("gAMA"),
|
||||||
cHRM = @bitCast("cHRM".*),
|
cHRM = fromName("cHRM"),
|
||||||
sRGB = @bitCast("sRGB".*),
|
sRGB = fromName("sRGB"),
|
||||||
iCCP = @bitCast("iCCP".*),
|
iCCP = fromName("iCCP"),
|
||||||
tEXt = @bitCast("tEXt".*),
|
tEXt = fromName("tEXt"),
|
||||||
zTXt = @bitCast("zTXt".*),
|
zTXt = fromName("zTXt"),
|
||||||
iTXt = @bitCast("iTXt".*),
|
iTXt = fromName("iTXt"),
|
||||||
bKGD = @bitCast("bKGD".*),
|
bKGD = fromName("bKGD"),
|
||||||
pHYs = @bitCast("pHYs".*),
|
pHYs = fromName("pHYs"),
|
||||||
sBIT = @bitCast("sBIT".*),
|
sBIT = fromName("sBIT"),
|
||||||
sPLT = @bitCast("sPLT".*),
|
sPLT = fromName("sPLT"),
|
||||||
hIST = @bitCast("hIST".*),
|
hIST = fromName("hIST"),
|
||||||
tIME = @bitCast("tIME".*),
|
tIME = fromName("tIME"),
|
||||||
_,
|
_,
|
||||||
|
|
||||||
|
fn fromName(name: *const [4]u8) u32 {
|
||||||
|
return @bitCast(name.*);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fromBytes(bytes: *const [4]u8) ChunkType {
|
||||||
|
return @enumFromInt(fromName(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toBytes(self: ChunkType) [4]u8 {
|
||||||
|
return @bitCast(@intFromEnum(self));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ancillary(self: ChunkType) bool {
|
pub fn ancillary(self: ChunkType) bool {
|
||||||
return @as([4]u8, @bitCast(self))[0] & 0b0010_0000 != 0;
|
return self.toBytes()[0] & 0b0010_0000 != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn private(self: ChunkType) bool {
|
pub fn private(self: ChunkType) bool {
|
||||||
return @as([4]u8, @bitCast(self))[1] & 0b0010_0000 != 0;
|
return self.toBytes()[1] & 0b0010_0000 != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn safeToCopy(self: ChunkType) bool {
|
pub fn safeToCopy(self: ChunkType) bool {
|
||||||
return @as([4]u8, @bitCast(self))[3] & 0b0010_0000 != 0;
|
return self.toBytes()[3] & 0b0010_0000 != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -460,6 +520,10 @@ pub const StandardKeyword = enum {
|
|||||||
pub fn isStandardKeyword(keyword: []const u8) ?StandardKeyword {
|
pub fn isStandardKeyword(keyword: []const u8) ?StandardKeyword {
|
||||||
return map.get(keyword);
|
return map.get(keyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The caller asserts that the buffer is at least `format.magic_length` bytes
|
/// The caller asserts that the buffer is at least `format.magic_length` bytes
|
||||||
@@ -477,7 +541,7 @@ pub fn info(buffer: []const u8) ?Header {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const chunk, _ = decodeChunk(buffer[format.magic_length..]) catch return null orelse return null;
|
const chunk, _ = (decodeChunk(buffer[format.magic_length..]) catch return null) orelse return null;
|
||||||
if (chunk.chunk_type != .IHDR) {
|
if (chunk.chunk_type != .IHDR) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -495,7 +559,7 @@ pub fn decodeChunk(buffer: []const u8) !?struct { Chunk, []const u8 } {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const length = std.mem.readInt(u32, rest[0..4], .big);
|
const length = std.mem.readInt(u32, rest[0..4], .big);
|
||||||
const chunk_type: ChunkType = @bitCast(rest[4..8].*);
|
const chunk_type: ChunkType = .fromBytes(rest[4..8]);
|
||||||
rest = rest[8..];
|
rest = rest[8..];
|
||||||
|
|
||||||
if (length > 0x7FFF_FFFF) {
|
if (length > 0x7FFF_FFFF) {
|
||||||
@@ -575,3 +639,7 @@ pub fn encodeChunks(chunks: []const Chunk, writer: *std.Io.Writer) !void {
|
|||||||
try writer.writeInt(u32, crc.final(), .big);
|
try writer.writeInt(u32, crc.final(), .big);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ const Header = union(enum) {
|
|||||||
pub fn initStatic(static: HeaderStatic) Header {
|
pub fn initStatic(static: HeaderStatic) Header {
|
||||||
return .{ .static = static };
|
return .{ .static = static };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const HeaderStreaming = void;
|
const HeaderStreaming = void;
|
||||||
@@ -36,6 +40,10 @@ const HeaderStatic = struct {
|
|||||||
const sample_rate: f64 = @floatFromInt(self.sample_rate);
|
const sample_rate: f64 = @floatFromInt(self.sample_rate);
|
||||||
return @floatCast(samples / sample_rate);
|
return @floatCast(samples / sample_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The caller asserts that the buffer is at least `format.magic_length` bytes
|
/// The caller asserts that the buffer is at least `format.magic_length` bytes
|
||||||
@@ -73,3 +81,7 @@ pub fn info(buffer: []const u8) ?Header {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,3 +68,7 @@ pub fn info(buffer: []const u8) ?Header {
|
|||||||
.color_space = @enumFromInt(color_space),
|
.color_space = @enumFromInt(color_space),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
pub const audio = @import("audio.zig");
|
pub const audio = @import("audio.zig");
|
||||||
pub const Format = @import("Format.zig");
|
pub const Format = @import("Format.zig");
|
||||||
pub const image = @import("image.zig");
|
pub const image = @import("image.zig");
|
||||||
@@ -7,3 +9,7 @@ pub const png = @import("png.zig");
|
|||||||
pub const qoa = @import("qoa.zig");
|
pub const qoa = @import("qoa.zig");
|
||||||
pub const qoi = @import("qoi.zig");
|
pub const qoi = @import("qoi.zig");
|
||||||
pub const stbi = @import("stbi.zig");
|
pub const stbi = @import("stbi.zig");
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,17 +5,20 @@ const image = @import("image.zig");
|
|||||||
const vm = @import("vecmath");
|
const vm = @import("vecmath");
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
io: std.Io,
|
||||||
|
|
||||||
|
mutex: std.Io.Mutex = .init,
|
||||||
allocations: std.AutoHashMapUnmanaged(*anyopaque, usize) = .empty,
|
allocations: std.AutoHashMapUnmanaged(*anyopaque, usize) = .empty,
|
||||||
mutex: std.Thread.Mutex = .{},
|
|
||||||
allocated_bytes: usize = 0,
|
allocated_bytes: usize = 0,
|
||||||
|
|
||||||
const alignment: std.mem.Alignment = .@"16";
|
const alignment: std.mem.Alignment = .@"16";
|
||||||
const VoidPtr = ?*align(alignment.toByteUnits()) anyopaque;
|
const VoidPtr = ?*align(alignment.toByteUnits()) anyopaque;
|
||||||
const log = std.log.scoped(.stbi);
|
const log = std.log.scoped(.stbi);
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) Self {
|
pub fn init(allocator: std.mem.Allocator, io: std.Io) Self {
|
||||||
return .{
|
return .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
|
.io = io,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +79,7 @@ pub fn loadStaticBuf(self: *Self, comptime W: u32, comptime H: u32, buf: []const
|
|||||||
return .{ .data = @as(*const [W * H]vm.Color, @ptrCast(@alignCast(res))).* };
|
return .{ .data = @as(*const [W * H]vm.Color, @ptrCast(@alignCast(res))).* };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn loadStaticIo(self: *Self, comptime W: u32, comptime H: u32, reader: *std.io.Reader) !image.Static(W, H) {
|
pub fn loadStaticIo(self: *Self, comptime W: u32, comptime H: u32, reader: *std.Io.Reader) !image.Static(W, H) {
|
||||||
current_self = self;
|
current_self = self;
|
||||||
defer current_self = undefined;
|
defer current_self = undefined;
|
||||||
|
|
||||||
@@ -109,7 +112,7 @@ pub fn loadDynamicBuf(self: *Self, buf: []const u8) !image.Dynamic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// On success, must free memory by calling `freeDynamic` method.
|
/// On success, must free memory by calling `freeDynamic` method.
|
||||||
pub fn loadDynamicIo(self: *Self, reader: *std.io.Reader) !image.Dynamic {
|
pub fn loadDynamicIo(self: *Self, reader: *std.Io.Reader) !image.Dynamic {
|
||||||
current_self = self;
|
current_self = self;
|
||||||
defer current_self = undefined;
|
defer current_self = undefined;
|
||||||
|
|
||||||
@@ -155,7 +158,7 @@ pub fn loadHdrBuf(self: *Self, buf: []const u8) !image.Hdr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// On success, must free memory by calling `freeHdr` method.
|
/// On success, must free memory by calling `freeHdr` method.
|
||||||
pub fn loadHdrIo(self: *Self, reader: *std.io.Reader) !image.Hdr {
|
pub fn loadHdrIo(self: *Self, reader: *std.Io.Reader) !image.Hdr {
|
||||||
current_self = self;
|
current_self = self;
|
||||||
defer current_self = undefined;
|
defer current_self = undefined;
|
||||||
|
|
||||||
@@ -243,8 +246,8 @@ threadlocal var current_self: *Self = undefined;
|
|||||||
export fn castle_media_stbi_malloc(size: usize) callconv(.c) VoidPtr {
|
export fn castle_media_stbi_malloc(size: usize) callconv(.c) VoidPtr {
|
||||||
const self = current_self;
|
const self = current_self;
|
||||||
|
|
||||||
self.mutex.lock();
|
self.mutex.lock(self.io) catch return null;
|
||||||
defer self.mutex.unlock();
|
defer self.mutex.unlock(self.io);
|
||||||
|
|
||||||
self.allocations.ensureUnusedCapacity(self.allocator, 1) catch return null;
|
self.allocations.ensureUnusedCapacity(self.allocator, 1) catch return null;
|
||||||
const memory = self.allocator.alignedAlloc(u8, alignment, size) catch return null;
|
const memory = self.allocator.alignedAlloc(u8, alignment, size) catch return null;
|
||||||
@@ -259,8 +262,8 @@ export fn castle_media_stbi_malloc(size: usize) callconv(.c) VoidPtr {
|
|||||||
export fn castle_media_stbi_realloc(maybe_ptr: VoidPtr, size: usize) callconv(.c) VoidPtr {
|
export fn castle_media_stbi_realloc(maybe_ptr: VoidPtr, size: usize) callconv(.c) VoidPtr {
|
||||||
const self = current_self;
|
const self = current_self;
|
||||||
|
|
||||||
self.mutex.lock();
|
self.mutex.lock(self.io) catch return null;
|
||||||
defer self.mutex.unlock();
|
defer self.mutex.unlock(self.io);
|
||||||
|
|
||||||
// NOTE If we were pedantic, we would consider the fact that we might not
|
// NOTE If we were pedantic, we would consider the fact that we might not
|
||||||
// need unused capacity if the memory doesn't get relocated.
|
// need unused capacity if the memory doesn't get relocated.
|
||||||
@@ -291,8 +294,8 @@ export fn castle_media_stbi_free(maybe_ptr: VoidPtr) callconv(.c) void {
|
|||||||
const self = current_self;
|
const self = current_self;
|
||||||
|
|
||||||
if (maybe_ptr) |ptr| {
|
if (maybe_ptr) |ptr| {
|
||||||
self.mutex.lock();
|
self.mutex.lockUncancelable(self.io);
|
||||||
defer self.mutex.unlock();
|
defer self.mutex.unlock(self.io);
|
||||||
|
|
||||||
const size = self.allocations.fetchRemove(ptr).?.value;
|
const size = self.allocations.fetchRemove(ptr).?.value;
|
||||||
self.allocated_bytes -= size;
|
self.allocated_bytes -= size;
|
||||||
@@ -301,3 +304,7 @@ export fn castle_media_stbi_free(maybe_ptr: VoidPtr) callconv(.c) void {
|
|||||||
self.allocator.free(memory);
|
self.allocator.free(memory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "refAllDecls" {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user