mirror of
https://github.com/oven-sh/bun
synced 2026-02-05 08:28:55 +00:00
Compare commits
1 Commits
dylan/pyth
...
jarred/shr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
280c7b0831 |
@@ -126,7 +126,7 @@ pub const PrintErr = error{
|
||||
|
||||
pub fn OOM(e: anyerror) noreturn {
|
||||
if (comptime bun.Environment.isDebug) {
|
||||
std.debug.assert(e == std.mem.Allocator.Error.OutOfMemory);
|
||||
assert(e == std.mem.Allocator.Error.OutOfMemory);
|
||||
}
|
||||
bun.outOfMemory();
|
||||
}
|
||||
@@ -246,6 +246,14 @@ pub fn todo(comptime fmt: []const u8, args: anytype) noreturn {
|
||||
std.debug.panic("TODO: " ++ fmt, args);
|
||||
}
|
||||
|
||||
fn RuntimeVoidWrap(comptime T: type) type {
|
||||
return struct {
|
||||
fn wrapped(fn_ptr: *const fn (*Parser) Result(T), p: *Parser) Result(T) {
|
||||
return fn_ptr(p);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn voidWrap(comptime T: type, comptime parsefn: *const fn (*Parser) Result(T)) *const fn (void, *Parser) Result(T) {
|
||||
const Wrapper = struct {
|
||||
fn wrapped(_: void, p: *Parser) Result(T) {
|
||||
@@ -954,12 +962,12 @@ fn parse_at_rule(
|
||||
name: []const u8,
|
||||
parser: *P,
|
||||
|
||||
pub fn parsefn(this: *@This(), input2: *Parser) Result(P.AtRuleParser.Prelude) {
|
||||
pub fn parsefn(this: *const @This(), input2: *Parser) Result(P.AtRuleParser.Prelude) {
|
||||
return P.AtRuleParser.parsePrelude(this.parser, this.name, input2);
|
||||
}
|
||||
};
|
||||
var closure = Closure{ .name = name, .parser = parser };
|
||||
const prelude: P.AtRuleParser.Prelude = switch (input.parseUntilBefore(delimiters, P.AtRuleParser.Prelude, &closure, Closure.parsefn)) {
|
||||
const closure = Closure{ .name = name, .parser = parser };
|
||||
const prelude: P.AtRuleParser.Prelude = switch (input.parseUntilBefore(delimiters, P.AtRuleParser.Prelude, *const Closure, &closure, Closure.parsefn)) {
|
||||
.result => |vvv| vvv,
|
||||
.err => |e| {
|
||||
// const end_position = input.position();
|
||||
@@ -1004,16 +1012,16 @@ fn parse_at_rule(
|
||||
prelude: P.AtRuleParser.Prelude,
|
||||
start: *const ParserState,
|
||||
parser: *P,
|
||||
pub fn parsefn(this: *@This(), input2: *Parser) Result(P.AtRuleParser.AtRule) {
|
||||
pub fn parsefn(this: *const @This(), input2: *Parser) Result(P.AtRuleParser.AtRule) {
|
||||
return P.AtRuleParser.parseBlock(this.parser, this.prelude, this.start, input2);
|
||||
}
|
||||
};
|
||||
var another_closure = AnotherClosure{
|
||||
const another_closure = AnotherClosure{
|
||||
.prelude = prelude,
|
||||
.start = start,
|
||||
.parser = parser,
|
||||
};
|
||||
return parse_nested_block(input, P.AtRuleParser.AtRule, &another_closure, AnotherClosure.parsefn);
|
||||
return parse_nested_block(input, P.AtRuleParser.AtRule, *const AnotherClosure, &another_closure, AnotherClosure.parsefn);
|
||||
},
|
||||
else => {
|
||||
bun.unreachablePanic("", .{});
|
||||
@@ -1099,7 +1107,7 @@ fn parse_qualified_rule(
|
||||
) Result(P.QualifiedRuleParser.QualifiedRule) {
|
||||
ValidQualifiedRuleParser(P);
|
||||
const prelude_result = brk: {
|
||||
const prelude = input.parseUntilBefore(delimiters, P.QualifiedRuleParser.Prelude, parser, P.QualifiedRuleParser.parsePrelude);
|
||||
const prelude = input.parseUntilBefore(delimiters, P.QualifiedRuleParser.Prelude, *P, parser, P.QualifiedRuleParser.parsePrelude);
|
||||
break :brk prelude;
|
||||
};
|
||||
if (input.expectCurlyBracketBlock().asErr()) |e| return .{ .err = e };
|
||||
@@ -1112,16 +1120,16 @@ fn parse_qualified_rule(
|
||||
prelude: P.QualifiedRuleParser.Prelude,
|
||||
parser: *P,
|
||||
|
||||
pub fn parsefn(this: *@This(), input2: *Parser) Result(P.QualifiedRuleParser.QualifiedRule) {
|
||||
pub fn parsefn(this: *const @This(), input2: *Parser) Result(P.QualifiedRuleParser.QualifiedRule) {
|
||||
return P.QualifiedRuleParser.parseBlock(this.parser, this.prelude, this.start, input2);
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
const closure = Closure{
|
||||
.start = start,
|
||||
.prelude = prelude,
|
||||
.parser = parser,
|
||||
};
|
||||
return parse_nested_block(input, P.QualifiedRuleParser.QualifiedRule, &closure, Closure.parsefn);
|
||||
return parse_nested_block(input, P.QualifiedRuleParser.QualifiedRule, *const Closure, &closure, Closure.parsefn);
|
||||
}
|
||||
|
||||
fn parse_until_before(
|
||||
@@ -1129,8 +1137,9 @@ fn parse_until_before(
|
||||
delimiters_: Delimiters,
|
||||
error_behavior: ParseUntilErrorBehavior,
|
||||
comptime T: type,
|
||||
closure: anytype,
|
||||
comptime parse_fn: *const fn (@TypeOf(closure), *Parser) Result(T),
|
||||
comptime Closure: type,
|
||||
closure: Closure,
|
||||
parse_fn: *const fn (Closure, *Parser) Result(T),
|
||||
) Result(T) {
|
||||
const delimiters = parser.stop_before.bitwiseOr(delimiters_);
|
||||
const result = result: {
|
||||
@@ -1143,7 +1152,7 @@ fn parse_until_before(
|
||||
.stop_before = delimiters,
|
||||
.import_records = parser.import_records,
|
||||
};
|
||||
const result = delimited_parser.parseEntirely(T, closure, parse_fn);
|
||||
const result = delimited_parser.parseEntirely(T, Closure, closure, parse_fn);
|
||||
if (error_behavior == .stop and result.isErr()) {
|
||||
return result;
|
||||
}
|
||||
@@ -1172,15 +1181,16 @@ fn parse_until_before(
|
||||
|
||||
// fn parse_until_before_impl(parser: *Parser, delimiters: Delimiters, error_behavior: Parse
|
||||
|
||||
pub fn parse_until_after(
|
||||
fn parse_until_after(
|
||||
parser: *Parser,
|
||||
delimiters: Delimiters,
|
||||
error_behavior: ParseUntilErrorBehavior,
|
||||
comptime T: type,
|
||||
closure: anytype,
|
||||
comptime parsefn: *const fn (@TypeOf(closure), *Parser) Result(T),
|
||||
comptime Closure: type,
|
||||
closure: Closure,
|
||||
parsefn: *const fn (Closure, *Parser) Result(T),
|
||||
) Result(T) {
|
||||
const result = parse_until_before(parser, delimiters, error_behavior, T, closure, parsefn);
|
||||
const result = parse_until_before(parser, delimiters, error_behavior, T, Closure, closure, parsefn);
|
||||
const is_err = result.isErr();
|
||||
if (error_behavior == .stop and is_err) {
|
||||
return result;
|
||||
@@ -1197,7 +1207,7 @@ pub fn parse_until_after(
|
||||
return result;
|
||||
}
|
||||
|
||||
fn parse_nested_block(parser: *Parser, comptime T: type, closure: anytype, comptime parsefn: *const fn (@TypeOf(closure), *Parser) Result(T)) Result(T) {
|
||||
fn parse_nested_block(parser: *Parser, comptime T: type, comptime Closure: type, closure: Closure, comptime parsefn: *const fn (Closure, *Parser) Result(T)) Result(T) {
|
||||
const block_type: BlockType = if (parser.at_start_of) |block_type| brk: {
|
||||
parser.at_start_of = null;
|
||||
break :brk block_type;
|
||||
@@ -1218,7 +1228,7 @@ fn parse_nested_block(parser: *Parser, comptime T: type, closure: anytype, compt
|
||||
.stop_before = closing_delimiter,
|
||||
.import_records = parser.import_records,
|
||||
};
|
||||
const result = nested_parser.parseEntirely(T, closure, parsefn);
|
||||
const result = nested_parser.parseEntirely(T, Closure, closure, parsefn);
|
||||
if (nested_parser.at_start_of) |block_type2| {
|
||||
consume_until_end_of_block(block_type2, &nested_parser.input.tokenizer);
|
||||
}
|
||||
@@ -2618,7 +2628,7 @@ pub fn StyleSheetParser(comptime P: type) type {
|
||||
.semicolon = true,
|
||||
.close_curly_bracket = true,
|
||||
};
|
||||
_ = this.input.parseUntilAfter(delimiters, void, {}, voidWrap(void, Parser.parseEmpty));
|
||||
_ = this.input.parseUntilAfter(delimiters, void, void, {}, voidWrap(void, Parser.parseEmpty));
|
||||
} else {
|
||||
return parse_at_rule(allocator, &start, name, this.input, P, this.parser);
|
||||
}
|
||||
@@ -3141,16 +3151,16 @@ pub fn RuleBodyParser(comptime P: type) type {
|
||||
const Closure = struct {
|
||||
parser: *P,
|
||||
name: []const u8,
|
||||
pub fn parsefn(self: *@This(), input: *Parser) Result(I) {
|
||||
pub fn parsefn(self: *const @This(), input: *Parser) Result(I) {
|
||||
if (input.expectColon().asErr()) |e| return .{ .err = e };
|
||||
return P.DeclarationParser.parseValue(self.parser, self.name, input);
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
const closure = Closure{
|
||||
.parser = this.parser,
|
||||
.name = name,
|
||||
};
|
||||
break :result parse_until_after(this.input, Delimiters{ .semicolon = true }, error_behavior, I, &closure, Closure.parsefn);
|
||||
break :result parse_until_after(this.input, Delimiters{ .semicolon = true }, error_behavior, I, *const Closure, &closure, Closure.parsefn);
|
||||
};
|
||||
if (result.isErr() and parse_qualified) {
|
||||
this.input.reset(&start);
|
||||
@@ -3182,7 +3192,7 @@ pub fn RuleBodyParser(comptime P: type) type {
|
||||
const token = tok.*;
|
||||
|
||||
const Closure = struct { token: Token, start: ParserState };
|
||||
break :result this.input.parseUntilAfter(Delimiters{ .semicolon = true }, I, &Closure{ .token = token, .start = start }, struct {
|
||||
break :result this.input.parseUntilAfter(Delimiters{ .semicolon = true }, I, *const Closure, &Closure{ .token = token, .start = start }, struct {
|
||||
pub fn parseFn(closure: *const Closure, i: *Parser) Result(I) {
|
||||
_ = i; // autofix
|
||||
return .{ .err = closure.start.sourceLocation().newUnexpectedTokenError(closure.token) };
|
||||
@@ -3355,7 +3365,7 @@ pub const Parser = struct {
|
||||
}
|
||||
|
||||
/// Implementation of Vec::<T>::parse
|
||||
pub fn parseList(this: *Parser, comptime T: type, comptime parse_one: *const fn (*Parser) Result(T)) Result(ArrayList(T)) {
|
||||
pub fn parseList(this: *Parser, comptime T: type, parse_one: *const fn (*Parser) Result(T)) Result(ArrayList(T)) {
|
||||
return this.parseCommaSeparated(T, parse_one);
|
||||
}
|
||||
|
||||
@@ -3373,25 +3383,29 @@ pub const Parser = struct {
|
||||
pub fn parseCommaSeparated(
|
||||
this: *Parser,
|
||||
comptime T: type,
|
||||
comptime parse_one: *const fn (*Parser) Result(T),
|
||||
parse_one: *const fn (*Parser) Result(T),
|
||||
) Result(ArrayList(T)) {
|
||||
return this.parseCommaSeparatedInternal(T, {}, voidWrap(T, parse_one), false);
|
||||
const Wrapper = RuntimeVoidWrap(T);
|
||||
const parse_fn = &Wrapper.wrapped;
|
||||
return this.parseCommaSeparatedInternal(T, @TypeOf(parse_one), parse_one, parse_fn, false);
|
||||
}
|
||||
|
||||
pub fn parseCommaSeparatedWithCtx(
|
||||
this: *Parser,
|
||||
comptime T: type,
|
||||
closure: anytype,
|
||||
comptime parse_one: *const fn (@TypeOf(closure), *Parser) Result(T),
|
||||
comptime Ctx: type,
|
||||
closure: Ctx,
|
||||
parse_one: *const fn (Ctx, *Parser) Result(T),
|
||||
) Result(ArrayList(T)) {
|
||||
return this.parseCommaSeparatedInternal(T, closure, parse_one, false);
|
||||
return this.parseCommaSeparatedInternal(T, Ctx, closure, parse_one, false);
|
||||
}
|
||||
|
||||
fn parseCommaSeparatedInternal(
|
||||
this: *Parser,
|
||||
comptime T: type,
|
||||
closure: anytype,
|
||||
comptime parse_one: *const fn (@TypeOf(closure), *Parser) Result(T),
|
||||
comptime Closure: type,
|
||||
closure: Closure,
|
||||
parse_one: *const fn (Closure, *Parser) Result(T),
|
||||
ignore_errors: bool,
|
||||
) Result(ArrayList(T)) {
|
||||
// Vec grows from 0 to 4 by default on first push(). So allocate with
|
||||
@@ -3408,7 +3422,7 @@ pub const Parser = struct {
|
||||
|
||||
while (true) {
|
||||
this.skipWhitespace(); // Unnecessary for correctness, but may help try() in parse_one rewind less.
|
||||
switch (this.parseUntilBefore(Delimiters{ .comma = true }, T, closure, parse_one)) {
|
||||
switch (this.parseUntilBefore(Delimiters{ .comma = true }, T, Closure, closure, parse_one)) {
|
||||
.result => |v| {
|
||||
values.append(alloc, v) catch unreachable;
|
||||
},
|
||||
@@ -3458,7 +3472,7 @@ pub const Parser = struct {
|
||||
return result;
|
||||
}
|
||||
|
||||
pub inline fn tryParseImpl(this: *Parser, comptime Ret: type, comptime func: anytype, args: anytype) Ret {
|
||||
pub fn tryParseImpl(this: *Parser, comptime Ret: type, comptime func: anytype, args: anytype) Ret {
|
||||
const start = this.state();
|
||||
const result = result: {
|
||||
break :result @call(.auto, func, args);
|
||||
@@ -3470,7 +3484,11 @@ pub const Parser = struct {
|
||||
}
|
||||
|
||||
pub inline fn parseNestedBlock(this: *Parser, comptime T: type, closure: anytype, comptime parsefn: *const fn (@TypeOf(closure), *Parser) Result(T)) Result(T) {
|
||||
return parse_nested_block(this, T, closure, parsefn);
|
||||
return parseNestedBlockT(this, T, @TypeOf(closure), closure, parsefn);
|
||||
}
|
||||
|
||||
pub inline fn parseNestedBlockT(this: *Parser, comptime T: type, comptime Closure: type, closure: Closure, comptime parsefn: *const fn (Closure, *Parser) Result(T)) Result(T) {
|
||||
return parse_nested_block(this, T, Closure, closure, parsefn);
|
||||
}
|
||||
|
||||
pub fn isExhausted(this: *Parser) bool {
|
||||
@@ -3731,12 +3749,12 @@ pub const Parser = struct {
|
||||
return .{ .err = start_location.newUnexpectedTokenError(tok.*) };
|
||||
}
|
||||
|
||||
pub fn position(this: *Parser) usize {
|
||||
pub fn position(this: *const Parser) usize {
|
||||
bun.debugAssert(bun.strings.isOnCharBoundary(this.input.tokenizer.src, this.input.tokenizer.position));
|
||||
return this.input.tokenizer.position;
|
||||
}
|
||||
|
||||
fn parseEmpty(_: *Parser) Result(void) {
|
||||
fn parseEmpty(_: *const Parser) Result(void) {
|
||||
return .{ .result = {} };
|
||||
}
|
||||
|
||||
@@ -3749,24 +3767,26 @@ pub const Parser = struct {
|
||||
this: *Parser,
|
||||
delimiters: Delimiters,
|
||||
comptime T: type,
|
||||
closure: anytype,
|
||||
comptime parse_fn: *const fn (@TypeOf(closure), *Parser) Result(T),
|
||||
comptime Closure: type,
|
||||
closure: Closure,
|
||||
parse_fn: *const fn (Closure, *Parser) Result(T),
|
||||
) Result(T) {
|
||||
return parse_until_after(
|
||||
this,
|
||||
delimiters,
|
||||
ParseUntilErrorBehavior.consume,
|
||||
T,
|
||||
Closure,
|
||||
closure,
|
||||
parse_fn,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn parseUntilBefore(this: *Parser, delimiters: Delimiters, comptime T: type, closure: anytype, comptime parse_fn: *const fn (@TypeOf(closure), *Parser) Result(T)) Result(T) {
|
||||
return parse_until_before(this, delimiters, .consume, T, closure, parse_fn);
|
||||
pub fn parseUntilBefore(this: *Parser, delimiters: Delimiters, comptime T: type, comptime Closure: type, closure: Closure, parse_fn: *const fn (Closure, *Parser) Result(T)) Result(T) {
|
||||
return parse_until_before(this, delimiters, .consume, T, Closure, closure, parse_fn);
|
||||
}
|
||||
|
||||
pub fn parseEntirely(this: *Parser, comptime T: type, closure: anytype, comptime parsefn: *const fn (@TypeOf(closure), *Parser) Result(T)) Result(T) {
|
||||
pub inline fn parseEntirely(this: *Parser, comptime T: type, comptime Closure: type, closure: Closure, parsefn: *const fn (Closure, *Parser) Result(T)) Result(T) {
|
||||
const result = switch (parsefn(closure, this)) {
|
||||
.err => |e| return .{ .err = e },
|
||||
.result => |v| v,
|
||||
@@ -3840,7 +3860,7 @@ pub const Parser = struct {
|
||||
if (this.import_records) |import_records| import_records.len = state_.import_record_count;
|
||||
}
|
||||
|
||||
pub fn state(this: *Parser) ParserState {
|
||||
pub fn state(this: *const Parser) ParserState {
|
||||
return ParserState{
|
||||
.position = this.input.tokenizer.getPosition(),
|
||||
.current_line_start_position = this.input.tokenizer.current_line_start_position,
|
||||
@@ -4249,18 +4269,18 @@ const Tokenizer = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn prev(this: *Tokenizer) Token {
|
||||
pub fn prev(this: *const Tokenizer) Token {
|
||||
bun.assert(this.position > 0);
|
||||
return this.previous;
|
||||
}
|
||||
|
||||
pub inline fn isEof(this: *Tokenizer) bool {
|
||||
pub inline fn isEof(this: *const Tokenizer) bool {
|
||||
return this.position >= this.src.len;
|
||||
}
|
||||
|
||||
pub fn seeFunction(this: *Tokenizer, name: []const u8) void {
|
||||
if (this.var_or_env_functions == .looking_for_them) {
|
||||
if (std.ascii.eqlIgnoreCase(name, "var") and std.ascii.eqlIgnoreCase(name, "env")) {
|
||||
if (name.len == 3 and bun.strings.eqlCaseInsensitiveASCII(name, "var", false) or bun.strings.eqlCaseInsensitiveASCII(name, "env", false)) {
|
||||
this.var_or_env_functions = .seen_at_least_one;
|
||||
}
|
||||
}
|
||||
@@ -5174,7 +5194,7 @@ const Tokenizer = struct {
|
||||
pub fn consumeNewline(this: *Tokenizer) void {
|
||||
const byte = this.nextByteUnchecked();
|
||||
if (bun.Environment.allow_assert) {
|
||||
std.debug.assert(byte == '\r' or byte == '\n' or byte == FORM_FEED_BYTE);
|
||||
assert(byte == '\r' or byte == '\n' or byte == FORM_FEED_BYTE);
|
||||
}
|
||||
this.position += 1;
|
||||
if (byte == '\r' and this.nextByte() == '\n') {
|
||||
@@ -5194,7 +5214,7 @@ const Tokenizer = struct {
|
||||
/// 11110xxx 0xF0..0xF7 First byte of a 4-byte character encoding
|
||||
/// 10xxxxxx 0x80..0xBF Continuation byte: one of 1-3 bytes following the first <--
|
||||
pub fn consumeContinuationByte(this: *Tokenizer) void {
|
||||
if (bun.Environment.allow_assert) std.debug.assert(this.nextByteUnchecked() & 0xC0 == 0x80);
|
||||
if (bun.Environment.allow_assert) assert(this.nextByteUnchecked() & 0xC0 == 0x80);
|
||||
// Continuation bytes contribute to column overcount. Note
|
||||
// that due to the special case for the 4-byte sequence intro,
|
||||
// we must use wrapping add here.
|
||||
@@ -5212,7 +5232,7 @@ const Tokenizer = struct {
|
||||
/// 11110xxx 0xF0..0xF7 First byte of a 4-byte character encoding <--
|
||||
/// 10xxxxxx 0x80..0xBF Continuation byte: one of 1-3 bytes following the first
|
||||
pub fn consume4byteIntro(this: *Tokenizer) void {
|
||||
if (bun.Environment.allow_assert) std.debug.assert(this.nextByteUnchecked() & 0xF0 == 0xF0);
|
||||
if (bun.Environment.allow_assert) assert(this.nextByteUnchecked() & 0xF0 == 0xF0);
|
||||
// This takes two UTF-16 characters to represent, so we
|
||||
// actually have an undercount.
|
||||
// this.current_line_start_position = self.current_line_start_position.wrapping_sub(1);
|
||||
@@ -5220,7 +5240,7 @@ const Tokenizer = struct {
|
||||
this.position += 1;
|
||||
}
|
||||
|
||||
pub fn isIdentStart(this: *Tokenizer) bool {
|
||||
pub fn isIdentStart(this: *const Tokenizer) bool {
|
||||
|
||||
// todo_stuff.match_byte
|
||||
return !this.isEof() and switch (this.nextByteUnchecked()) {
|
||||
@@ -5239,19 +5259,19 @@ const Tokenizer = struct {
|
||||
|
||||
/// If true, the input has at least `n` bytes left *after* the current one.
|
||||
/// That is, `tokenizer.char_at(n)` will not panic.
|
||||
fn hasAtLeast(this: *Tokenizer, n: usize) bool {
|
||||
fn hasAtLeast(this: *const Tokenizer, n: usize) bool {
|
||||
return this.position + n < this.src.len;
|
||||
}
|
||||
|
||||
fn hasNewlineAt(this: *Tokenizer, offset: usize) bool {
|
||||
fn hasNewlineAt(this: *const Tokenizer, offset: usize) bool {
|
||||
return this.position + offset < this.src.len and switch (this.byteAt(offset)) {
|
||||
'\n', '\r', FORM_FEED_BYTE => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn startsWith(this: *Tokenizer, comptime needle: []const u8) bool {
|
||||
return std.mem.eql(u8, this.src[this.position .. this.position + needle.len], needle);
|
||||
pub fn startsWith(this: *const Tokenizer, comptime needle: []const u8) bool {
|
||||
return bun.strings.hasPrefixComptime(this.src[this.position..], needle);
|
||||
}
|
||||
|
||||
/// Advance over N bytes in the input. This function can advance
|
||||
@@ -5264,8 +5284,8 @@ const Tokenizer = struct {
|
||||
// rejected.
|
||||
for (0..n) |i| {
|
||||
const b = this.byteAt(i);
|
||||
std.debug.assert(std.ascii.isASCII(b) or (b & 0xF0 != 0xF0 and b & 0xC0 != 0x80));
|
||||
std.debug.assert(b != '\r' and b != '\n' and b != '\x0C');
|
||||
assert(std.ascii.isASCII(b) or (b & 0xF0 != 0xF0 and b & 0xC0 != 0x80));
|
||||
assert(b != '\r' and b != '\n' and b != '\x0C');
|
||||
}
|
||||
}
|
||||
this.position += n;
|
||||
@@ -5273,7 +5293,7 @@ const Tokenizer = struct {
|
||||
|
||||
/// Advance over any kind of byte, excluding newlines.
|
||||
pub fn consumeKnownByte(this: *Tokenizer, byte: u8) void {
|
||||
if (bun.Environment.allow_assert) std.debug.assert(byte != '\r' and byte != '\n' and byte != FORM_FEED_BYTE);
|
||||
if (bun.Environment.allow_assert) assert(byte != '\r' and byte != '\n' and byte != FORM_FEED_BYTE);
|
||||
this.position += 1;
|
||||
// Continuation bytes contribute to column overcount.
|
||||
if (byte & 0xF0 == 0xF0) {
|
||||
@@ -5287,25 +5307,25 @@ const Tokenizer = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn byteAt(this: *Tokenizer, n: usize) u8 {
|
||||
pub inline fn byteAt(this: *const Tokenizer, n: usize) u8 {
|
||||
return this.src[this.position + n];
|
||||
}
|
||||
|
||||
pub inline fn nextByte(this: *Tokenizer) ?u8 {
|
||||
pub inline fn nextByte(this: *const Tokenizer) ?u8 {
|
||||
if (this.isEof()) return null;
|
||||
return this.src[this.position];
|
||||
}
|
||||
|
||||
pub inline fn nextChar(this: *Tokenizer) u32 {
|
||||
pub inline fn nextChar(this: *const Tokenizer) u32 {
|
||||
const len = bun.strings.utf8ByteSequenceLength(this.src[this.position]);
|
||||
return bun.strings.decodeWTF8RuneT(this.src[this.position..].ptr[0..4], len, u32, bun.strings.unicode_replacement);
|
||||
}
|
||||
|
||||
pub inline fn nextByteUnchecked(this: *Tokenizer) u8 {
|
||||
pub inline fn nextByteUnchecked(this: *const Tokenizer) u8 {
|
||||
return this.src[this.position];
|
||||
}
|
||||
|
||||
pub inline fn sliceFrom(this: *Tokenizer, start: usize) []const u8 {
|
||||
pub inline fn sliceFrom(this: *const Tokenizer, start: usize) []const u8 {
|
||||
return this.src[start..this.position];
|
||||
}
|
||||
};
|
||||
@@ -6828,3 +6848,5 @@ fn restrict_prec(buf: []u8, comptime prec: u8) struct { []u8, Notation } {
|
||||
pub inline fn fract(val: f32) f32 {
|
||||
return val - @trunc(val);
|
||||
}
|
||||
|
||||
const assert = bun.assert;
|
||||
|
||||
@@ -153,7 +153,7 @@ pub const DeclarationBlock = struct {
|
||||
context: *css.PropertyHandlerContext,
|
||||
) void {
|
||||
const handle = struct {
|
||||
inline fn handle(
|
||||
fn handle(
|
||||
self: *This,
|
||||
ctx: *css.PropertyHandlerContext,
|
||||
hndlr: *DeclarationHandler,
|
||||
@@ -299,12 +299,12 @@ pub fn parse_declaration(
|
||||
property_id: css.PropertyId,
|
||||
options: *const css.ParserOptions,
|
||||
};
|
||||
var closure = Closure{
|
||||
const closure = Closure{
|
||||
.property_id = property_id,
|
||||
.options = options,
|
||||
};
|
||||
const property = switch (input.parseUntilBefore(delimiters, css.Property, &closure, struct {
|
||||
pub fn parseFn(this: *Closure, input2: *css.Parser) Result(css.Property) {
|
||||
const property = switch (input.parseUntilBefore(delimiters, css.Property, *const Closure, &closure, struct {
|
||||
pub fn parseFn(this: *const Closure, input2: *css.Parser) Result(css.Property) {
|
||||
return css.Property.parse(this.property_id, input2, this.options);
|
||||
}
|
||||
}.parseFn)) {
|
||||
|
||||
@@ -156,7 +156,7 @@ pub fn canTransitivelyImplementEql(comptime T: type) bool {
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn eql(comptime T: type, lhs: *const T, rhs: *const T) bool {
|
||||
pub fn eql(comptime T: type, lhs: *const T, rhs: *const T) bool {
|
||||
const tyinfo = comptime @typeInfo(T);
|
||||
if (comptime tyinfo == .Pointer) {
|
||||
if (comptime T == []const u8) return bun.strings.eql(lhs.*, rhs.*);
|
||||
@@ -264,7 +264,7 @@ pub inline fn deepClone(comptime T: type, this: *const T, allocator: Allocator)
|
||||
}
|
||||
|
||||
const Angle = css_values.angle.Angle;
|
||||
pub inline fn tryFromAngle(comptime T: type, angle: Angle) ?T {
|
||||
pub fn tryFromAngle(comptime T: type, angle: Angle) ?T {
|
||||
return switch (T) {
|
||||
CSSNumber => CSSNumberFns.tryFromAngle(angle),
|
||||
Angle => return Angle.tryFromAngle(angle),
|
||||
@@ -285,7 +285,7 @@ pub inline fn trySign(comptime T: type, val: *const T) ?f32 {
|
||||
pub inline fn tryMap(
|
||||
comptime T: type,
|
||||
val: *const T,
|
||||
comptime map_fn: *const fn (a: f32) f32,
|
||||
map_fn: *const fn (a: f32) f32,
|
||||
) ?T {
|
||||
return switch (T) {
|
||||
CSSNumber => map_fn(val.*),
|
||||
@@ -301,31 +301,33 @@ pub inline fn tryOpTo(
|
||||
comptime R: type,
|
||||
lhs: *const T,
|
||||
rhs: *const T,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) R,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, a: f32, b: f32) R,
|
||||
) ?R {
|
||||
return switch (T) {
|
||||
CSSNumber => op_fn(ctx, lhs.*, rhs.*),
|
||||
else => {
|
||||
if (@hasDecl(T, "opTo")) return T.opTo(lhs, rhs, R, ctx, op_fn);
|
||||
return T.tryOpTo(lhs, rhs, R, ctx, op_fn);
|
||||
if (@hasDecl(T, "opTo")) return T.opTo(lhs, rhs, R, Ctx, ctx, op_fn);
|
||||
return T.tryOpTo(lhs, rhs, R, Ctx, ctx, op_fn);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn tryOp(
|
||||
pub fn tryOp(
|
||||
comptime T: type,
|
||||
lhs: *const T,
|
||||
rhs: *const T,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) f32,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, f32, f32) f32,
|
||||
) ?T {
|
||||
return switch (T) {
|
||||
Angle => Angle.tryOp(lhs, rhs, ctx, op_fn),
|
||||
Angle => Angle.tryOp(lhs, rhs, Ctx, ctx, op_fn),
|
||||
CSSNumber => op_fn(ctx, lhs.*, rhs.*),
|
||||
else => {
|
||||
if (@hasDecl(T, "op")) return T.op(lhs, rhs, ctx, op_fn);
|
||||
return T.tryOp(lhs, rhs, ctx, op_fn);
|
||||
if (@hasDecl(T, "op")) return T.op(lhs, rhs, Ctx, ctx, op_fn);
|
||||
return T.tryOp(lhs, rhs, Ctx, ctx, op_fn);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ pub const MediaList = struct {
|
||||
pub fn parse(input: *css.Parser) Result(MediaList) {
|
||||
var media_queries = ArrayList(MediaQuery){};
|
||||
while (true) {
|
||||
const mq = switch (input.parseUntilBefore(css.Delimiters{ .comma = true }, MediaQuery, {}, css.voidWrap(MediaQuery, MediaQuery.parse))) {
|
||||
const mq = switch (input.parseUntilBefore(css.Delimiters{ .comma = true }, MediaQuery, void, {}, css.voidWrap(MediaQuery, MediaQuery.parse))) {
|
||||
.result => |v| v,
|
||||
.err => |e| {
|
||||
if (e.kind == .basic and e.kind.basic == .end_of_input) break;
|
||||
|
||||
@@ -198,7 +198,7 @@ pub fn Printer(comptime Writer: type) type {
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn getImportRecords(this: *This) PrintErr!*const bun.BabyList(bun.ImportRecord) {
|
||||
pub fn getImportRecords(this: *This) PrintErr!*const bun.BabyList(bun.ImportRecord) {
|
||||
if (this.import_records) |import_records| return import_records;
|
||||
try this.addNoImportRecordError();
|
||||
unreachable;
|
||||
@@ -215,13 +215,13 @@ pub fn Printer(comptime Writer: type) type {
|
||||
return this.addNoImportRecordError();
|
||||
}
|
||||
|
||||
pub inline fn importRecord(this: *Printer(Writer), import_record_idx: u32) PrintErr!*const bun.ImportRecord {
|
||||
pub fn importRecord(this: *Printer(Writer), import_record_idx: u32) PrintErr!*const bun.ImportRecord {
|
||||
if (this.import_records) |import_records| return import_records.at(import_record_idx);
|
||||
try this.addNoImportRecordError();
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub inline fn getImportRecordUrl(this: *This, import_record_idx: u32) PrintErr![]const u8 {
|
||||
pub fn getImportRecordUrl(this: *This, import_record_idx: u32) PrintErr![]const u8 {
|
||||
return (try this.importRecord(import_record_idx)).path.text;
|
||||
}
|
||||
|
||||
|
||||
@@ -925,7 +925,7 @@ pub const UnresolvedColor = union(enum) {
|
||||
const Closure = struct {
|
||||
options: *const css.ParserOptions,
|
||||
parser: *ComponentParser,
|
||||
pub fn parsefn(this: *@This(), input2: *css.Parser) Result(UnresolvedColor) {
|
||||
pub fn parsefn(this: *const @This(), input2: *css.Parser) Result(UnresolvedColor) {
|
||||
return this.parser.parseRelative(input2, HSL, UnresolvedColor, @This().innerParseFn, .{this.options});
|
||||
}
|
||||
pub fn innerParseFn(i: *css.Parser, p: *ComponentParser, opts: *const css.ParserOptions) Result(UnresolvedColor) {
|
||||
@@ -951,7 +951,7 @@ pub const UnresolvedColor = union(enum) {
|
||||
} };
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
const closure = Closure{
|
||||
.options = options,
|
||||
.parser = &parser,
|
||||
};
|
||||
@@ -960,8 +960,8 @@ pub const UnresolvedColor = union(enum) {
|
||||
const Closure = struct {
|
||||
options: *const css.ParserOptions,
|
||||
parser: *ComponentParser,
|
||||
pub fn parsefn(this: *@This(), input2: *css.Parser) Result(UnresolvedColor) {
|
||||
const light = switch (input2.parseUntilBefore(css.Delimiters{ .comma = true }, TokenList, this, @This().parsefn2)) {
|
||||
pub fn parsefn(this: *const @This(), input2: *css.Parser) Result(UnresolvedColor) {
|
||||
const light = switch (input2.parseUntilBefore(css.Delimiters{ .comma = true }, TokenList, *const css.ParserOptions, this.options, @This().parsefn2)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -982,11 +982,11 @@ pub const UnresolvedColor = union(enum) {
|
||||
} };
|
||||
}
|
||||
|
||||
pub fn parsefn2(this: *@This(), input2: *css.Parser) Result(TokenList) {
|
||||
return TokenListFns.parse(input2, this.options, 1);
|
||||
pub fn parsefn2(parser_options: *const css.ParserOptions, input2: *css.Parser) Result(TokenList) {
|
||||
return TokenListFns.parse(input2, parser_options, 1);
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
const closure = Closure{
|
||||
.options = options,
|
||||
.parser = &parser,
|
||||
};
|
||||
@@ -1412,10 +1412,9 @@ pub const UnparsedProperty = struct {
|
||||
value: TokenList,
|
||||
|
||||
pub fn parse(property_id: css.PropertyId, input: *css.Parser, options: *const css.ParserOptions) Result(UnparsedProperty) {
|
||||
const Closure = struct { options: *const css.ParserOptions };
|
||||
const value = switch (input.parseUntilBefore(css.Delimiters{ .bang = true, .semicolon = true }, css.TokenList, &Closure{ .options = options }, struct {
|
||||
pub fn parseFn(self: *const Closure, i: *css.Parser) Result(TokenList) {
|
||||
return TokenList.parse(i, self.options, 0);
|
||||
const value = switch (input.parseUntilBefore(css.Delimiters{ .bang = true, .semicolon = true }, css.TokenList, *const css.ParserOptions, options, struct {
|
||||
pub fn parseFn(parser_options: *const css.ParserOptions, i: *css.Parser) Result(TokenList) {
|
||||
return TokenList.parse(i, parser_options, 0);
|
||||
}
|
||||
}.parseFn)) {
|
||||
.result => |v| v,
|
||||
@@ -1444,24 +1443,19 @@ pub const CustomProperty = struct {
|
||||
|
||||
pub fn parse(name: CustomPropertyName, input: *css.Parser, options: *const css.ParserOptions) Result(CustomProperty) {
|
||||
const Closure = struct {
|
||||
options: *const css.ParserOptions,
|
||||
|
||||
pub fn parsefn(this: *@This(), input2: *css.Parser) Result(TokenList) {
|
||||
return TokenListFns.parse(input2, this.options, 0);
|
||||
pub fn parsefn(parser_options: *const css.ParserOptions, input2: *css.Parser) Result(TokenList) {
|
||||
return TokenListFns.parse(input2, parser_options, 0);
|
||||
}
|
||||
};
|
||||
|
||||
var closure = Closure{
|
||||
.options = options,
|
||||
};
|
||||
|
||||
const value = switch (input.parseUntilBefore(
|
||||
css.Delimiters{
|
||||
.bang = true,
|
||||
.semicolon = true,
|
||||
},
|
||||
TokenList,
|
||||
&closure,
|
||||
*const css.ParserOptions,
|
||||
options,
|
||||
Closure.parsefn,
|
||||
)) {
|
||||
.result => |v| v,
|
||||
|
||||
@@ -241,7 +241,7 @@ pub fn StyleRule(comptime R: type) type {
|
||||
|
||||
/// Returns whether this rule is a duplicate of another rule.
|
||||
/// This means it has the same selectors and properties.
|
||||
pub inline fn isDuplicate(this: *const This, other: *const This) bool {
|
||||
pub fn isDuplicate(this: *const This, other: *const This) bool {
|
||||
return this.declarations.len() == other.declarations.len() and
|
||||
this.selectors.eql(&other.selectors) and
|
||||
brk: {
|
||||
|
||||
@@ -1550,7 +1550,7 @@ pub fn GenericSelectorList(comptime Impl: type) type {
|
||||
.nesting_requirement = nesting_requirement,
|
||||
.parser = parser,
|
||||
};
|
||||
const selector = input.parseUntilBefore(css.Delimiters{ .comma = true }, SelectorT, &closure, Closure.parsefn);
|
||||
const selector = input.parseUntilBefore(css.Delimiters{ .comma = true }, SelectorT, *Closure, &closure, Closure.parsefn);
|
||||
|
||||
const was_ok = selector.isOk();
|
||||
switch (selector) {
|
||||
@@ -1610,7 +1610,7 @@ pub fn GenericSelectorList(comptime Impl: type) type {
|
||||
.nesting_requirement = nesting_requirement,
|
||||
.parser = parser,
|
||||
};
|
||||
const selector = input.parseUntilBefore(css.Delimiters{ .comma = true }, SelectorT, &closure, Closure.parsefn);
|
||||
const selector = input.parseUntilBefore(css.Delimiters{ .comma = true }, SelectorT, *Closure, &closure, Closure.parsefn);
|
||||
|
||||
const was_ok = selector.isOk();
|
||||
switch (selector) {
|
||||
|
||||
@@ -866,7 +866,7 @@ pub const serialize = struct {
|
||||
}
|
||||
|
||||
const Helpers = struct {
|
||||
pub inline fn writePrefixed(
|
||||
pub fn writePrefixed(
|
||||
d: *Printer(W),
|
||||
prefix: css.VendorPrefix,
|
||||
comptime val: []const u8,
|
||||
@@ -881,7 +881,7 @@ pub const serialize = struct {
|
||||
try vp.toCss(W, d);
|
||||
try d.writeStr(val);
|
||||
}
|
||||
pub inline fn pseudo(
|
||||
pub fn pseudo(
|
||||
d: *Printer(W),
|
||||
comptime key: []const u8,
|
||||
comptime s: []const u8,
|
||||
@@ -1583,7 +1583,7 @@ const CompoundSelectorIter = struct {
|
||||
/// .split(|x| x.is_combinator()) // splits the slice into subslices by elements that match over the predicate
|
||||
/// .rev() // reverse
|
||||
/// ```
|
||||
pub inline fn next(this: *@This()) ?[]const parser.Component {
|
||||
pub fn next(this: *@This()) ?[]const parser.Component {
|
||||
// Since we iterating backwards, we convert all indices into "backwards form" by doing `this.sel.components.items.len - 1 - i`
|
||||
while (this.i < this.sel.components.items.len) {
|
||||
const next_index: ?usize = next_index: {
|
||||
|
||||
@@ -53,7 +53,7 @@ pub fn SmallList(comptime T: type, comptime N: comptime_int) type {
|
||||
var values: @This() = .{};
|
||||
while (true) {
|
||||
input.skipWhitespace();
|
||||
switch (input.parseUntilBefore(Delimiters{ .comma = true }, T, {}, parseFn)) {
|
||||
switch (input.parseUntilBefore(Delimiters{ .comma = true }, T, void, {}, parseFn)) {
|
||||
.result => |v| {
|
||||
values.append(input.allocator(), v);
|
||||
},
|
||||
|
||||
@@ -170,7 +170,7 @@ pub const Angle = union(Tag) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn map(this: *const Angle, comptime opfn: *const fn (f32) f32) Angle {
|
||||
pub fn map(this: *const Angle, opfn: *const fn (f32) f32) Angle {
|
||||
return switch (this.*) {
|
||||
.deg => |deg| .{ .deg = opfn(deg) },
|
||||
.rad => |rad| .{ .rad = opfn(rad) },
|
||||
@@ -179,7 +179,7 @@ pub const Angle = union(Tag) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn tryMap(this: *const Angle, comptime opfn: *const fn (f32) f32) ?Angle {
|
||||
pub fn tryMap(this: *const Angle, opfn: *const fn (f32) f32) ?Angle {
|
||||
return map(this, opfn);
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ pub const Angle = union(Tag) {
|
||||
return a + b;
|
||||
}
|
||||
};
|
||||
return Angle.op(&this, &rhs, {}, addfn.add);
|
||||
return Angle.op(&this, &rhs, void, {}, addfn.add);
|
||||
}
|
||||
|
||||
pub fn tryAdd(this: *const Angle, _: std.mem.Allocator, rhs: *const Angle) ?Angle {
|
||||
@@ -217,27 +217,30 @@ pub const Angle = union(Tag) {
|
||||
pub fn tryOp(
|
||||
this: *const Angle,
|
||||
other: *const Angle,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) f32,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, f32, f32) f32,
|
||||
) ?Angle {
|
||||
return Angle.op(this, other, ctx, op_fn);
|
||||
return Angle.op(this, other, Ctx, ctx, op_fn);
|
||||
}
|
||||
|
||||
pub fn tryOpTo(
|
||||
this: *const Angle,
|
||||
other: *const Angle,
|
||||
comptime R: type,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) R,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, f32, f32) R,
|
||||
) ?R {
|
||||
return Angle.opTo(this, other, R, ctx, op_fn);
|
||||
return Angle.opTo(this, other, R, Ctx, ctx, op_fn);
|
||||
}
|
||||
|
||||
pub fn op(
|
||||
this: *const Angle,
|
||||
other: *const Angle,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) f32,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, a: f32, b: f32) f32,
|
||||
) Angle {
|
||||
// PERF: not sure if this is faster
|
||||
const self_tag: u8 = @intFromEnum(this.*);
|
||||
@@ -261,8 +264,9 @@ pub const Angle = union(Tag) {
|
||||
this: *const Angle,
|
||||
other: *const Angle,
|
||||
comptime T: type,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) T,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, a: f32, b: f32) T,
|
||||
) T {
|
||||
// PERF: not sure if this is faster
|
||||
const self_tag: u8 = @intFromEnum(this.*);
|
||||
|
||||
@@ -45,6 +45,32 @@ pub fn needsDeepclone(comptime V: type) bool {
|
||||
};
|
||||
}
|
||||
|
||||
const CalcUnit = enum {
|
||||
abs,
|
||||
acos,
|
||||
asin,
|
||||
atan,
|
||||
atan2,
|
||||
calc,
|
||||
clamp,
|
||||
cos,
|
||||
exp,
|
||||
hypot,
|
||||
log,
|
||||
max,
|
||||
min,
|
||||
mod,
|
||||
pow,
|
||||
rem,
|
||||
round,
|
||||
sign,
|
||||
sin,
|
||||
sqrt,
|
||||
tan,
|
||||
|
||||
pub const Map = bun.ComptimeEnumMap(CalcUnit);
|
||||
};
|
||||
|
||||
/// A mathematical expression used within the `calc()` function.
|
||||
///
|
||||
/// This type supports generic value types. Values such as `Length`, `Percentage`,
|
||||
@@ -266,39 +292,14 @@ pub fn Calc(comptime V: type) type {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
return parseWith(input, {}, Fn.parseWithFn);
|
||||
return parseWith(input, void, {}, Fn.parseWithFn);
|
||||
}
|
||||
|
||||
const CalcUnit = enum {
|
||||
abs,
|
||||
acos,
|
||||
asin,
|
||||
atan,
|
||||
atan2,
|
||||
calc,
|
||||
clamp,
|
||||
cos,
|
||||
exp,
|
||||
hypot,
|
||||
log,
|
||||
max,
|
||||
min,
|
||||
mod,
|
||||
pow,
|
||||
rem,
|
||||
round,
|
||||
sign,
|
||||
sin,
|
||||
sqrt,
|
||||
tan,
|
||||
|
||||
pub const Map = bun.ComptimeEnumMap(CalcUnit);
|
||||
};
|
||||
|
||||
pub fn parseWith(
|
||||
input: *css.Parser,
|
||||
ctx: anytype,
|
||||
comptime parseIdent: *const fn (@TypeOf(ctx), []const u8) ?This,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
parseIdent: *const fn (Ctx, []const u8) ?This,
|
||||
) Result(This) {
|
||||
const location = input.currentSourceLocation();
|
||||
const f = switch (input.expectFunction()) {
|
||||
@@ -308,14 +309,22 @@ pub fn Calc(comptime V: type) type {
|
||||
|
||||
switch (CalcUnit.Map.getAnyCase(f) orelse return .{ .err = location.newUnexpectedTokenError(.{ .ident = f }) }) {
|
||||
.calc => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
return This.parseSum(i, self.ctx, parseIdent);
|
||||
pub fn parseNestedBlockFn(state: *const State, i: *css.Parser) Result(This) {
|
||||
return This.parseSum(i, Ctx, state.ctx, state.parse_ident);
|
||||
}
|
||||
};
|
||||
var closure = Closure{ .ctx = ctx };
|
||||
const calc = switch (input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn)) {
|
||||
|
||||
const calc = switch (input.parseNestedBlockT(
|
||||
This,
|
||||
*const State,
|
||||
&State{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parseIdent,
|
||||
},
|
||||
Closure.parseNestedBlockFn,
|
||||
)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -329,17 +338,20 @@ pub fn Calc(comptime V: type) type {
|
||||
} };
|
||||
},
|
||||
.min => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(ArrayList(This)) {
|
||||
return i.parseCommaSeparatedWithCtx(This, self, @This().parseOne);
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(ArrayList(This)) {
|
||||
return i.parseCommaSeparatedWithCtx(This, *const State, self, @This().parseOne);
|
||||
}
|
||||
pub fn parseOne(self: *@This(), i: *css.Parser) Result(This) {
|
||||
return This.parseSum(i, self.ctx, parseIdent);
|
||||
pub fn parseOne(self: *const State, i: *css.Parser) Result(This) {
|
||||
return This.parseSum(i, Ctx, self.ctx, self.parse_ident);
|
||||
}
|
||||
};
|
||||
var closure = Closure{ .ctx = ctx };
|
||||
var reduced = switch (input.parseNestedBlock(ArrayList(This), &closure, Closure.parseNestedBlockFn)) {
|
||||
|
||||
var reduced = switch (input.parseNestedBlockT(ArrayList(This), *const State, &State{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -360,17 +372,19 @@ pub fn Calc(comptime V: type) type {
|
||||
} };
|
||||
},
|
||||
.max => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(ArrayList(This)) {
|
||||
return i.parseCommaSeparatedWithCtx(This, self, @This().parseOne);
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(ArrayList(This)) {
|
||||
return i.parseCommaSeparatedWithCtx(This, *const State, self, @This().parseOne);
|
||||
}
|
||||
pub fn parseOne(self: *@This(), i: *css.Parser) Result(This) {
|
||||
return This.parseSum(i, self.ctx, parseIdent);
|
||||
pub fn parseOne(self: *const State, i: *css.Parser) Result(This) {
|
||||
return This.parseSum(i, Ctx, self.ctx, self.parse_ident);
|
||||
}
|
||||
};
|
||||
var closure = Closure{ .ctx = ctx };
|
||||
var reduced = switch (input.parseNestedBlock(ArrayList(This), &closure, Closure.parseNestedBlockFn)) {
|
||||
var reduced = switch (input.parseNestedBlockT(ArrayList(This), *const State, &State{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -390,37 +404,33 @@ pub fn Calc(comptime V: type) type {
|
||||
},
|
||||
.clamp => {
|
||||
const ClosureResult = struct { ?This, This, ?This };
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
|
||||
pub fn parseNestedBlock(self: *@This(), i: *css.Parser) Result(ClosureResult) {
|
||||
const min = switch (This.parseSum(i, self, parseIdentWrapper)) {
|
||||
pub fn parseNestedBlock(self: *const State, i: *css.Parser) Result(ClosureResult) {
|
||||
const min = switch (This.parseSum(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
if (i.expectComma().asErr()) |e| return .{ .err = e };
|
||||
const center = switch (This.parseSum(i, self, parseIdentWrapper)) {
|
||||
const center = switch (This.parseSum(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
if (i.expectComma().asErr()) |e| return .{ .err = e };
|
||||
const max = switch (This.parseSum(i, self, parseIdentWrapper)) {
|
||||
const max = switch (This.parseSum(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
return .{ .result = .{ min, center, max } };
|
||||
}
|
||||
|
||||
pub fn parseIdentWrapper(self: *@This(), ident: []const u8) ?This {
|
||||
return parseIdent(self.ctx, ident);
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
.ctx = ctx,
|
||||
};
|
||||
var min, var center, var max = switch (input.parseNestedBlock(
|
||||
var min, var center, var max = switch (input.parseNestedBlockT(
|
||||
ClosureResult,
|
||||
&closure,
|
||||
*const State,
|
||||
&State{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parseIdent,
|
||||
},
|
||||
Closure.parseNestedBlock,
|
||||
)) {
|
||||
.result => |vv| vv,
|
||||
@@ -492,9 +502,9 @@ pub fn Calc(comptime V: type) type {
|
||||
} };
|
||||
},
|
||||
.round => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(This) {
|
||||
const strategy = if (i.tryParse(RoundingStrategy.parse, .{}).asValue()) |s| brk: {
|
||||
if (i.expectComma().asErr()) |e| return .{ .err = e };
|
||||
break :brk s;
|
||||
@@ -503,11 +513,11 @@ pub fn Calc(comptime V: type) type {
|
||||
const OpAndFallbackCtx = struct {
|
||||
strategy: RoundingStrategy,
|
||||
|
||||
pub fn op(this: *const @This(), a: f32, b: f32) f32 {
|
||||
pub fn op(this: @This(), a: f32, b: f32) f32 {
|
||||
return round({}, a, b, this.strategy);
|
||||
}
|
||||
|
||||
pub fn fallback(this: *const @This(), a: This, b: This) MathFunction(V) {
|
||||
pub fn fallback(this: @This(), a: This, b: This) MathFunction(V) {
|
||||
return MathFunction(V){
|
||||
.round = .{
|
||||
.strategy = this.strategy,
|
||||
@@ -517,36 +527,40 @@ pub fn Calc(comptime V: type) type {
|
||||
};
|
||||
}
|
||||
};
|
||||
var ctx_for_op_and_fallback = OpAndFallbackCtx{
|
||||
const ctx_for_op_and_fallback = OpAndFallbackCtx{
|
||||
.strategy = strategy,
|
||||
};
|
||||
return This.parseMathFn(
|
||||
i,
|
||||
&ctx_for_op_and_fallback,
|
||||
OpAndFallbackCtx,
|
||||
ctx_for_op_and_fallback,
|
||||
OpAndFallbackCtx.op,
|
||||
OpAndFallbackCtx.fallback,
|
||||
Ctx,
|
||||
self.ctx,
|
||||
parseIdent,
|
||||
self.parse_ident,
|
||||
);
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
|
||||
return input.parseNestedBlockT(This, *const State, &.{
|
||||
.ctx = ctx,
|
||||
};
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn);
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn);
|
||||
},
|
||||
.rem => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(This) {
|
||||
return This.parseMathFn(
|
||||
i,
|
||||
void,
|
||||
{},
|
||||
@This().rem,
|
||||
mathFunctionRem,
|
||||
Ctx,
|
||||
self.ctx,
|
||||
parseIdent,
|
||||
self.parse_ident,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -562,23 +576,25 @@ pub fn Calc(comptime V: type) type {
|
||||
};
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
|
||||
return input.parseNestedBlockT(This, *const State, &State{
|
||||
.ctx = ctx,
|
||||
};
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn);
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn);
|
||||
},
|
||||
.mod => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(This) {
|
||||
return This.parseMathFn(
|
||||
i,
|
||||
void,
|
||||
{},
|
||||
@This().modulo,
|
||||
mathFunctionMod,
|
||||
Ctx,
|
||||
self.ctx,
|
||||
parseIdent,
|
||||
self.parse_ident,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -595,34 +611,35 @@ pub fn Calc(comptime V: type) type {
|
||||
};
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
|
||||
return input.parseNestedBlockT(This, *const State, &State{
|
||||
.ctx = ctx,
|
||||
};
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn);
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn);
|
||||
},
|
||||
.sin => {
|
||||
return This.parseTrig(input, .sin, false, ctx, parseIdent);
|
||||
return This.parseTrig(input, .sin, false, Ctx, ctx, parseIdent);
|
||||
},
|
||||
.cos => {
|
||||
return This.parseTrig(input, .cos, false, ctx, parseIdent);
|
||||
return This.parseTrig(input, .cos, false, Ctx, ctx, parseIdent);
|
||||
},
|
||||
.tan => {
|
||||
return This.parseTrig(input, .tan, false, ctx, parseIdent);
|
||||
return This.parseTrig(input, .tan, false, Ctx, ctx, parseIdent);
|
||||
},
|
||||
.asin => {
|
||||
return This.parseTrig(input, .asin, true, ctx, parseIdent);
|
||||
return This.parseTrig(input, .asin, true, Ctx, ctx, parseIdent);
|
||||
},
|
||||
.acos => {
|
||||
return This.parseTrig(input, .acos, true, ctx, parseIdent);
|
||||
return This.parseTrig(input, .acos, true, Ctx, ctx, parseIdent);
|
||||
},
|
||||
.atan => {
|
||||
return This.parseTrig(input, .atan, true, ctx, parseIdent);
|
||||
return This.parseTrig(input, .atan, true, Ctx, ctx, parseIdent);
|
||||
},
|
||||
.atan2 => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
const res = switch (This.parseAtan2(i, self.ctx, parseIdent)) {
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(This) {
|
||||
const res = switch (This.parseAtan2(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |v| v,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -639,21 +656,23 @@ pub fn Calc(comptime V: type) type {
|
||||
return .{ .err = i.newCustomError(css.ParserError{ .invalid_value = {} }) };
|
||||
}
|
||||
};
|
||||
var closure = Closure{ .ctx = ctx };
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn);
|
||||
return input.parseNestedBlockT(This, *const State, &State{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn);
|
||||
},
|
||||
.pow => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
const a = switch (This.parseNumeric(i, self.ctx, parseIdent)) {
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(This) {
|
||||
const a = switch (This.parseNumeric(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
|
||||
if (i.expectComma().asErr()) |e| return .{ .err = e };
|
||||
|
||||
const b = switch (This.parseNumeric(i, self.ctx, parseIdent)) {
|
||||
const b = switch (This.parseNumeric(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -663,19 +682,21 @@ pub fn Calc(comptime V: type) type {
|
||||
} };
|
||||
}
|
||||
};
|
||||
var closure = Closure{ .ctx = ctx };
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn);
|
||||
return input.parseNestedBlockT(This, *const State, &State{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn);
|
||||
},
|
||||
.log => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
const value = switch (This.parseNumeric(i, self.ctx, parseIdent)) {
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(This) {
|
||||
const value = switch (This.parseNumeric(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
if (i.tryParse(css.Parser.expectComma, .{}).isOk()) {
|
||||
const base = switch (This.parseNumeric(i, self.ctx, parseIdent)) {
|
||||
const base = switch (This.parseNumeric(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -684,20 +705,22 @@ pub fn Calc(comptime V: type) type {
|
||||
return .{ .result = This{ .number = std.math.log(f32, std.math.e, value) } };
|
||||
}
|
||||
};
|
||||
var closure = Closure{ .ctx = ctx };
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn);
|
||||
return input.parseNestedBlockT(This, *const State, &State{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn);
|
||||
},
|
||||
.sqrt => {
|
||||
return This.parseNumericFn(input, .sqrt, ctx, parseIdent);
|
||||
return This.parseNumericFn(input, .sqrt, Ctx, ctx, parseIdent);
|
||||
},
|
||||
.exp => {
|
||||
return This.parseNumericFn(input, .exp, ctx, parseIdent);
|
||||
return This.parseNumericFn(input, .exp, Ctx, ctx, parseIdent);
|
||||
},
|
||||
.hypot => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
var args = switch (i.parseCommaSeparatedWithCtx(This, self, parseOne)) {
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(This) {
|
||||
var args = switch (i.parseCommaSeparatedWithCtx(This, *const State, self, parseOne)) {
|
||||
.result => |v| v,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -717,18 +740,20 @@ pub fn Calc(comptime V: type) type {
|
||||
} };
|
||||
}
|
||||
|
||||
pub fn parseOne(self: *@This(), i: *css.Parser) Result(This) {
|
||||
return This.parseSum(i, self.ctx, parseIdent);
|
||||
pub fn parseOne(self: *const State, i: *css.Parser) Result(This) {
|
||||
return This.parseSum(i, Ctx, self.ctx, self.parse_ident);
|
||||
}
|
||||
};
|
||||
var closure = Closure{ .ctx = ctx };
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn);
|
||||
return input.parseNestedBlockT(This, *const State, &State{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn);
|
||||
},
|
||||
.abs => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
const v = switch (This.parseSum(i, self.ctx, parseIdent)) {
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(This) {
|
||||
const v = switch (This.parseSum(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -743,14 +768,16 @@ pub fn Calc(comptime V: type) type {
|
||||
};
|
||||
}
|
||||
};
|
||||
var closure = Closure{ .ctx = ctx };
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn);
|
||||
return input.parseNestedBlockT(This, *const State, &State{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn);
|
||||
},
|
||||
.sign => {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
const v = switch (This.parseSum(i, self.ctx, parseIdent)) {
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(This) {
|
||||
const v = switch (This.parseSum(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -786,25 +813,36 @@ pub fn Calc(comptime V: type) type {
|
||||
} };
|
||||
}
|
||||
};
|
||||
var closure = Closure{ .ctx = ctx };
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn);
|
||||
return input.parseNestedBlockT(This, *const State, &State{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parseNumericFn(input: *css.Parser, comptime op: enum { sqrt, exp }, ctx: anytype, comptime parse_ident: *const fn (@TypeOf(ctx), []const u8) ?This) Result(This) {
|
||||
const Closure = struct { ctx: @TypeOf(ctx) };
|
||||
var closure = Closure{ .ctx = ctx };
|
||||
const NumericFnOp = enum { sqrt, exp };
|
||||
pub fn parseNumericFn(input: *css.Parser, op: NumericFnOp, comptime Ctx: type, ctx: Ctx, parse_ident: *const fn (Ctx, []const u8) ?This) Result(This) {
|
||||
const Closure = struct {
|
||||
ctx: Ctx,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
op: NumericFnOp,
|
||||
};
|
||||
const closure = Closure{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parse_ident,
|
||||
.op = op,
|
||||
};
|
||||
return input.parseNestedBlock(This, &closure, struct {
|
||||
pub fn parseNestedBlockFn(self: *Closure, i: *css.Parser) Result(This) {
|
||||
const v = switch (This.parseNumeric(i, self.ctx, parse_ident)) {
|
||||
pub fn parseNestedBlockFn(self: *const Closure, i: *css.Parser) Result(This) {
|
||||
const v = switch (This.parseNumeric(i, Ctx, self.ctx, self.parse_ident)) {
|
||||
.result => |v| v,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
|
||||
return .{
|
||||
.result = Calc(V){
|
||||
.number = switch (op) {
|
||||
.number = switch (self.op) {
|
||||
.sqrt => std.math.sqrt(v),
|
||||
.exp => std.math.exp(v),
|
||||
},
|
||||
@@ -816,23 +854,25 @@ pub fn Calc(comptime V: type) type {
|
||||
|
||||
pub fn parseMathFn(
|
||||
input: *css.Parser,
|
||||
ctx_for_op_and_fallback: anytype,
|
||||
comptime op: *const fn (@TypeOf(ctx_for_op_and_fallback), f32, f32) f32,
|
||||
comptime fallback: *const fn (@TypeOf(ctx_for_op_and_fallback), This, This) MathFunction(V),
|
||||
ctx_for_parse_ident: anytype,
|
||||
comptime parse_ident: *const fn (@TypeOf(ctx_for_parse_ident), []const u8) ?This,
|
||||
comptime CtxForOpAndFallback: type,
|
||||
ctx_for_op_and_fallback: CtxForOpAndFallback,
|
||||
op: *const fn (CtxForOpAndFallback, f32, f32) f32,
|
||||
fallback: *const fn (CtxForOpAndFallback, This, This) MathFunction(V),
|
||||
comptime CtxForParseIdent: type,
|
||||
ctx_for_parse_ident: CtxForParseIdent,
|
||||
parse_ident: *const fn (CtxForParseIdent, []const u8) ?This,
|
||||
) Result(This) {
|
||||
const a = switch (This.parseSum(input, ctx_for_parse_ident, parse_ident)) {
|
||||
const a = switch (This.parseSum(input, CtxForParseIdent, ctx_for_parse_ident, parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
if (input.expectComma().asErr()) |e| return .{ .err = e };
|
||||
const b = switch (This.parseSum(input, ctx_for_parse_ident, parse_ident)) {
|
||||
const b = switch (This.parseSum(input, CtxForParseIdent, ctx_for_parse_ident, parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
|
||||
const val = This.applyOp(&a, &b, input.allocator(), ctx_for_op_and_fallback, op) orelse This{
|
||||
const val = This.applyOp(&a, &b, input.allocator(), CtxForOpAndFallback, ctx_for_op_and_fallback, op) orelse This{
|
||||
.function = bun.create(
|
||||
input.allocator(),
|
||||
MathFunction(V),
|
||||
@@ -843,12 +883,13 @@ pub fn Calc(comptime V: type) type {
|
||||
return .{ .result = val };
|
||||
}
|
||||
|
||||
pub fn parseSum(
|
||||
fn parseSum(
|
||||
input: *css.Parser,
|
||||
ctx: anytype,
|
||||
comptime parse_ident: *const fn (@TypeOf(ctx), []const u8) ?This,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
) Result(This) {
|
||||
var cur = switch (This.parseProduct(input, ctx, parse_ident)) {
|
||||
var cur = switch (This.parseProduct(input, Ctx, ctx, parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -871,13 +912,13 @@ pub fn Calc(comptime V: type) type {
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
if (next_tok.* == .delim and next_tok.delim == '+') {
|
||||
const next = switch (Calc(V).parseProduct(input, ctx, parse_ident)) {
|
||||
const next = switch (Calc(V).parseProduct(input, Ctx, ctx, parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
cur = cur.add(input.allocator(), next);
|
||||
} else if (next_tok.* == .delim and next_tok.delim == '-') {
|
||||
var rhs = switch (This.parseProduct(input, ctx, parse_ident)) {
|
||||
var rhs = switch (This.parseProduct(input, Ctx, ctx, parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -897,8 +938,9 @@ pub fn Calc(comptime V: type) type {
|
||||
|
||||
pub fn parseProduct(
|
||||
input: *css.Parser,
|
||||
ctx: anytype,
|
||||
comptime parse_ident: *const fn (@TypeOf(ctx), []const u8) ?This,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
) Result(This) {
|
||||
var node = switch (This.parseValue(input, ctx, parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
@@ -916,7 +958,7 @@ pub fn Calc(comptime V: type) type {
|
||||
|
||||
if (tok.* == .delim and tok.delim == '*') {
|
||||
// At least one of the operands must be a number.
|
||||
const rhs = switch (This.parseValue(input, ctx, parse_ident)) {
|
||||
const rhs = switch (This.parseValueT(input, Ctx, ctx, parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -930,7 +972,7 @@ pub fn Calc(comptime V: type) type {
|
||||
return .{ .err = input.newUnexpectedTokenError(.{ .delim = '*' }) };
|
||||
}
|
||||
} else if (tok.* == .delim and tok.delim == '/') {
|
||||
const rhs = switch (This.parseValue(input, ctx, parse_ident)) {
|
||||
const rhs = switch (This.parseValueT(input, Ctx, ctx, parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -951,11 +993,20 @@ pub fn Calc(comptime V: type) type {
|
||||
pub fn parseValue(
|
||||
input: *css.Parser,
|
||||
ctx: anytype,
|
||||
comptime parse_ident: *const fn (@TypeOf(ctx), []const u8) ?This,
|
||||
parse_ident: *const fn (@TypeOf(ctx), []const u8) ?This,
|
||||
) Result(This) {
|
||||
return parseValueT(input, @TypeOf(ctx), ctx, parse_ident);
|
||||
}
|
||||
|
||||
fn parseValueT(
|
||||
input: *css.Parser,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
parseIdent: *const fn (Ctx, []const u8) ?This,
|
||||
) Result(This) {
|
||||
|
||||
// Parse nested calc() and other math functions.
|
||||
if (input.tryParse(This.parse, .{}).asValue()) |_calc| {
|
||||
const calc: This = _calc;
|
||||
if (input.tryParse(This.parse, .{}).asValue()) |calc| {
|
||||
switch (calc) {
|
||||
.function => |f| return switch (f.*) {
|
||||
.calc => |c| .{ .result = c },
|
||||
@@ -966,16 +1017,16 @@ pub fn Calc(comptime V: type) type {
|
||||
}
|
||||
|
||||
if (input.tryParse(css.Parser.expectParenthesisBlock, .{}).isOk()) {
|
||||
const State = ClosureState(Ctx, This);
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
pub fn parseNestedBlockFn(self: *@This(), i: *css.Parser) Result(This) {
|
||||
return This.parseSum(i, self.ctx, parse_ident);
|
||||
pub fn parseNestedBlockFn(self: *const State, i: *css.Parser) Result(This) {
|
||||
return This.parseSum(i, Ctx, self.ctx, self.parse_ident);
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
return input.parseNestedBlock(This, &State{
|
||||
.ctx = ctx,
|
||||
};
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBlockFn);
|
||||
.parse_ident = parseIdent,
|
||||
}, Closure.parseNestedBlockFn);
|
||||
}
|
||||
|
||||
if (input.tryParse(css.Parser.expectNumber, .{}).asValue()) |num| {
|
||||
@@ -988,7 +1039,7 @@ pub fn Calc(comptime V: type) type {
|
||||
|
||||
const location = input.currentSourceLocation();
|
||||
if (input.tryParse(css.Parser.expectIdent, .{}).asValue()) |ident| {
|
||||
if (parse_ident(ctx, ident)) |c| {
|
||||
if (parseIdent(ctx, ident)) |c| {
|
||||
return .{ .result = c };
|
||||
}
|
||||
|
||||
@@ -1008,40 +1059,42 @@ pub fn Calc(comptime V: type) type {
|
||||
} };
|
||||
}
|
||||
|
||||
const TrigFn = enum {
|
||||
sin,
|
||||
cos,
|
||||
tan,
|
||||
asin,
|
||||
acos,
|
||||
atan,
|
||||
|
||||
pub fn run(this: @This(), x: f32) f32 {
|
||||
return switch (this) {
|
||||
.sin => std.math.sin(x),
|
||||
.cos => std.math.cos(x),
|
||||
.tan => std.math.tan(x),
|
||||
.asin => std.math.asin(x),
|
||||
.acos => std.math.acos(x),
|
||||
.atan => std.math.atan(x),
|
||||
};
|
||||
}
|
||||
};
|
||||
pub fn parseTrig(
|
||||
input: *css.Parser,
|
||||
comptime trig_fn_kind: enum {
|
||||
sin,
|
||||
cos,
|
||||
tan,
|
||||
asin,
|
||||
acos,
|
||||
atan,
|
||||
},
|
||||
trig_fn: TrigFn,
|
||||
to_angle: bool,
|
||||
ctx: anytype,
|
||||
comptime parse_ident: *const fn (@TypeOf(ctx), []const u8) ?This,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
) Result(This) {
|
||||
const trig_fn = struct {
|
||||
pub fn run(x: f32) f32 {
|
||||
const mathfn = comptime switch (trig_fn_kind) {
|
||||
.sin => std.math.sin,
|
||||
.cos => std.math.cos,
|
||||
.tan => std.math.tan,
|
||||
.asin => std.math.asin,
|
||||
.acos => std.math.acos,
|
||||
.atan => std.math.atan,
|
||||
};
|
||||
return mathfn(x);
|
||||
}
|
||||
};
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
ctx: Ctx,
|
||||
to_angle: bool,
|
||||
|
||||
pub fn parseNestedBockFn(this: *@This(), i: *css.Parser) Result(This) {
|
||||
trig_fn: TrigFn,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
pub fn parseNestedBockFn(this: *const @This(), i: *css.Parser) Result(This) {
|
||||
const v = switch (Calc(Angle).parseSum(
|
||||
i,
|
||||
*const @This(),
|
||||
this,
|
||||
@This().parseIdentFn,
|
||||
)) {
|
||||
@@ -1052,9 +1105,9 @@ pub fn Calc(comptime V: type) type {
|
||||
const rad = rad: {
|
||||
switch (v) {
|
||||
.value => |angle| {
|
||||
if (!this.to_angle) break :rad trig_fn.run(angle.toRadians());
|
||||
if (!this.to_angle) break :rad this.trig_fn.run(angle.toRadians());
|
||||
},
|
||||
.number => break :rad trig_fn.run(v.number),
|
||||
.number => break :rad this.trig_fn.run(v.number),
|
||||
else => {},
|
||||
}
|
||||
return .{ .err = i.newCustomError(css.ParserError{ .invalid_value = {} }) };
|
||||
@@ -1076,15 +1129,17 @@ pub fn Calc(comptime V: type) type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parseIdentFn(this: *@This(), ident: []const u8) ?Calc(Angle) {
|
||||
const v = parse_ident(this.ctx, ident) orelse return null;
|
||||
pub fn parseIdentFn(this: *const @This(), ident: []const u8) ?Calc(Angle) {
|
||||
const v = this.parse_ident(this.ctx, ident) orelse return null;
|
||||
if (v == .number) return .{ .number = v.number };
|
||||
return null;
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
const closure = Closure{
|
||||
.ctx = ctx,
|
||||
.to_angle = to_angle,
|
||||
.trig_fn = trig_fn,
|
||||
.parse_ident = parse_ident,
|
||||
};
|
||||
return input.parseNestedBlock(This, &closure, Closure.parseNestedBockFn);
|
||||
}
|
||||
@@ -1099,10 +1154,10 @@ pub fn Calc(comptime V: type) type {
|
||||
|
||||
pub fn parseAtan2(
|
||||
input: *css.Parser,
|
||||
ctx: anytype,
|
||||
comptime parse_ident: *const fn (@TypeOf(ctx), []const u8) ?This,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
) Result(Angle) {
|
||||
const Ctx = @TypeOf(ctx);
|
||||
|
||||
// atan2 supports arguments of any <number>, <dimension>, or <percentage>, even ones that wouldn't
|
||||
// normally be supported by V. The only requirement is that the arguments be of the same type.
|
||||
@@ -1124,18 +1179,20 @@ pub fn Calc(comptime V: type) type {
|
||||
}
|
||||
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
ctx: Ctx,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
|
||||
pub fn parseIdentFn(self: *@This(), ident: []const u8) ?Calc(CSSNumber) {
|
||||
const v = parse_ident(self.ctx, ident) orelse return null;
|
||||
pub fn parseIdentFn(self: *const @This(), ident: []const u8) ?Calc(CSSNumber) {
|
||||
const v = self.parse_ident(self.ctx, ident) orelse return null;
|
||||
if (v == .number) return .{ .number = v.number };
|
||||
return null;
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
const closure = Closure{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parse_ident,
|
||||
};
|
||||
return Calc(CSSNumber).parseAtan2Args(input, &closure, Closure.parseIdentFn);
|
||||
return Calc(CSSNumber).parseAtan2Args(input, *const Closure, &closure, Closure.parseIdentFn);
|
||||
}
|
||||
|
||||
inline fn tryParseAtan2Args(
|
||||
@@ -1145,20 +1202,21 @@ pub fn Calc(comptime V: type) type {
|
||||
ctx: Ctx,
|
||||
) Result(Angle) {
|
||||
const func = ParseIdentNone(Ctx, Value).func;
|
||||
return input.tryParseImpl(Result(Angle), Calc(Value).parseAtan2Args, .{ input, ctx, func });
|
||||
return input.tryParseImpl(Result(Angle), Calc(Value).parseAtan2Args, .{ input, Ctx, ctx, func });
|
||||
}
|
||||
|
||||
pub fn parseAtan2Args(
|
||||
input: *css.Parser,
|
||||
ctx: anytype,
|
||||
comptime parse_ident: *const fn (@TypeOf(ctx), []const u8) ?This,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
) Result(Angle) {
|
||||
const a = switch (This.parseSum(input, ctx, parse_ident)) {
|
||||
const a = switch (This.parseSum(input, Ctx, ctx, parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
if (input.expectComma().asErr()) |e| return .{ .err = e };
|
||||
const b = switch (This.parseSum(input, ctx, parse_ident)) {
|
||||
const b = switch (This.parseSum(input, Ctx, ctx, parse_ident)) {
|
||||
.result => |vv| vv,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -1169,7 +1227,7 @@ pub fn Calc(comptime V: type) type {
|
||||
return .{ .rad = std.math.atan2(x, y) };
|
||||
}
|
||||
};
|
||||
if (css.generic.tryOpTo(V, Angle, a.value, b.value, {}, Fn.opToFn)) |v| {
|
||||
if (css.generic.tryOpTo(V, Angle, a.value, b.value, void, {}, Fn.opToFn)) |v| {
|
||||
return .{ .result = v };
|
||||
}
|
||||
} else if (a == .number and b == .number) {
|
||||
@@ -1185,22 +1243,25 @@ pub fn Calc(comptime V: type) type {
|
||||
|
||||
pub fn parseNumeric(
|
||||
input: *css.Parser,
|
||||
ctx: anytype,
|
||||
comptime parse_ident: *const fn (@TypeOf(ctx), []const u8) ?This,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
) Result(f32) {
|
||||
const Closure = struct {
|
||||
ctx: @TypeOf(ctx),
|
||||
ctx: Ctx,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
|
||||
pub fn parseIdentFn(self: *@This(), ident: []const u8) ?Calc(CSSNumber) {
|
||||
const v = parse_ident(self.ctx, ident) orelse return null;
|
||||
pub fn parseIdentFn(self: *const @This(), ident: []const u8) ?Calc(CSSNumber) {
|
||||
const v = self.parse_ident(self.ctx, ident) orelse return null;
|
||||
if (v == .number) return .{ .number = v.number };
|
||||
return null;
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
const closure = Closure{
|
||||
.ctx = ctx,
|
||||
.parse_ident = parse_ident,
|
||||
};
|
||||
const v: Calc(CSSNumber) = switch (Calc(CSSNumber).parseSum(input, &closure, Closure.parseIdentFn)) {
|
||||
const v: Calc(CSSNumber) = switch (Calc(CSSNumber).parseSum(input, *const Closure, &closure, Closure.parseIdentFn)) {
|
||||
.result => |v| v,
|
||||
.err => |e| return .{ .err = e },
|
||||
};
|
||||
@@ -1220,7 +1281,7 @@ pub fn Calc(comptime V: type) type {
|
||||
}
|
||||
|
||||
if (args.items.len == 2) {
|
||||
return .{ .result = This.applyOp(&args.items[0], &args.items[1], allocator, {}, hypot) };
|
||||
return .{ .result = This.applyOp(&args.items[0], &args.items[1], allocator, void, {}, hypot) };
|
||||
}
|
||||
|
||||
var i: usize = 0;
|
||||
@@ -1238,7 +1299,7 @@ pub fn Calc(comptime V: type) type {
|
||||
return a + bun.powf(b, 2);
|
||||
}
|
||||
};
|
||||
sum = This.applyOp(&sum, arg, allocator, {}, Fn.applyOpFn) orelse {
|
||||
sum = This.applyOp(&sum, arg, allocator, void, {}, Fn.applyOpFn) orelse {
|
||||
errored = true;
|
||||
break;
|
||||
};
|
||||
@@ -1253,11 +1314,12 @@ pub fn Calc(comptime V: type) type {
|
||||
a: *const This,
|
||||
b: *const This,
|
||||
allocator: std.mem.Allocator,
|
||||
ctx: anytype,
|
||||
comptime op: *const fn (@TypeOf(ctx), f32, f32) f32,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op: *const fn (Ctx, f32, f32) f32,
|
||||
) ?This {
|
||||
if (a.* == .value and b.* == .value) {
|
||||
if (css.generic.tryOp(V, a.value, b.value, ctx, op)) |v| {
|
||||
if (css.generic.tryOp(V, a.value, b.value, Ctx, ctx, op)) |v| {
|
||||
return This{
|
||||
.value = bun.create(
|
||||
allocator,
|
||||
@@ -1278,7 +1340,7 @@ pub fn Calc(comptime V: type) type {
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn applyMap(this: *const This, allocator: Allocator, comptime op: *const fn (f32) f32) ?This {
|
||||
pub fn applyMap(this: *const This, allocator: Allocator, op: *const fn (f32) f32) ?This {
|
||||
switch (this.*) {
|
||||
.number => |n| return This{ .number = op(n) },
|
||||
.value => |v| {
|
||||
@@ -1848,3 +1910,10 @@ pub const Constant = enum {
|
||||
fn absf(a: f32) f32 {
|
||||
return @abs(a);
|
||||
}
|
||||
|
||||
fn ClosureState(comptime Ctx: type, comptime This: type) type {
|
||||
return struct {
|
||||
ctx: Ctx,
|
||||
parse_ident: *const fn (Ctx, []const u8) ?This,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2273,7 +2273,7 @@ const RelativeComponentParser = struct {
|
||||
angle: Angle,
|
||||
parser: *const RelativeComponentParser,
|
||||
pub fn tryParseFn(i: *css.Parser, t: *@This()) Result(Angle) {
|
||||
if (Calc(Angle).parseWith(i, t, @This().calcParseIdentFn).asValue()) |val| {
|
||||
if (Calc(Angle).parseWith(i, *@This(), t, @This().calcParseIdentFn).asValue()) |val| {
|
||||
if (val == .value) {
|
||||
return .{ .result = val.value.* };
|
||||
}
|
||||
@@ -2323,7 +2323,7 @@ const RelativeComponentParser = struct {
|
||||
percentage: Percentage = .{ .v = 0 },
|
||||
|
||||
pub fn parsefn(i: *css.Parser, self: *@This()) Result(Percentage) {
|
||||
if (Calc(Percentage).parseWith(i, self, @This().calcparseident).asValue()) |calc_value| {
|
||||
if (Calc(Percentage).parseWith(i, *@This(), self, @This().calcparseident).asValue()) |calc_value| {
|
||||
if (calc_value == .value) return .{ .result = calc_value.value.* };
|
||||
}
|
||||
return .{ .err = i.newCustomError(css.ParserError.invalid_value) };
|
||||
@@ -2369,7 +2369,7 @@ const RelativeComponentParser = struct {
|
||||
var _closure = Closure{ .self = this };
|
||||
if (input.tryParse(struct {
|
||||
pub fn parseFn(i: *css.Parser, closure: *Closure) Result(Percentage) {
|
||||
const calc_value = switch (Calc(Percentage).parseWith(i, closure, parseIdentFn)) {
|
||||
const calc_value = switch (Calc(Percentage).parseWith(i, *Closure, closure, parseIdentFn)) {
|
||||
.result => |v| v,
|
||||
.err => return .{ .err = i.newCustomError(css.ParserError.invalid_value) },
|
||||
};
|
||||
@@ -2434,16 +2434,16 @@ const RelativeComponentParser = struct {
|
||||
p: *const RelativeComponentParser,
|
||||
allowed_types: ChannelType,
|
||||
|
||||
pub fn parseIdentFn(self: *@This(), ident: []const u8) ?Calc(f32) {
|
||||
pub fn parseIdentFn(self: *const @This(), ident: []const u8) ?Calc(f32) {
|
||||
const v = self.p.getIdent(ident, self.allowed_types) orelse return null;
|
||||
return .{ .number = v };
|
||||
}
|
||||
};
|
||||
var closure = Closure{
|
||||
const closure = Closure{
|
||||
.p = this,
|
||||
.allowed_types = allowed_types,
|
||||
};
|
||||
if (Calc(f32).parseWith(input, &closure, Closure.parseIdentFn).asValue()) |calc_val| {
|
||||
if (Calc(f32).parseWith(input, *const Closure, &closure, Closure.parseIdentFn).asValue()) |calc_val| {
|
||||
// PERF: I don't like this redundant allocation
|
||||
if (calc_val == .value) return .{ .result = calc_val.value.* };
|
||||
if (calc_val == .number) return .{ .result = calc_val.number };
|
||||
|
||||
@@ -538,7 +538,7 @@ pub const ConicGradient = struct {
|
||||
|
||||
pub fn parse(input: *css.Parser) Result(ConicGradient) {
|
||||
const angle = input.tryParse(struct {
|
||||
inline fn parse(i: *css.Parser) Result(Angle) {
|
||||
fn parse(i: *css.Parser) Result(Angle) {
|
||||
if (i.expectIdentMatching("from").asErr()) |e| return .{ .err = e };
|
||||
// Spec allows unitless zero angles for gradients.
|
||||
// https://w3c.github.io/csswg-drafts/css-images-4/#valdef-conic-gradient-angle
|
||||
@@ -547,7 +547,7 @@ pub const ConicGradient = struct {
|
||||
}.parse, .{}).unwrapOr(Angle{ .deg = 0.0 });
|
||||
|
||||
const position = input.tryParse(struct {
|
||||
inline fn parse(i: *css.Parser) Result(Position) {
|
||||
fn parse(i: *css.Parser) Result(Position) {
|
||||
if (i.expectIdentMatching("at").asErr()) |e| return .{ .err = e };
|
||||
return Position.parse(i);
|
||||
}
|
||||
@@ -1543,6 +1543,7 @@ pub fn parseItems(comptime D: type, input: *css.Parser) Result(ArrayList(Gradien
|
||||
if (input.parseUntilBefore(
|
||||
css.Delimiters{ .comma = true },
|
||||
void,
|
||||
Closure,
|
||||
Closure{ .items = &items, .seen_stop = &seen_stop },
|
||||
struct {
|
||||
fn parse(closure: Closure, i: *css.Parser) Result(void) {
|
||||
|
||||
@@ -373,7 +373,7 @@ pub const LengthValue = union(enum) {
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn map(this: *const @This(), comptime map_fn: *const fn (f32) f32) LengthValue {
|
||||
pub fn map(this: *const @This(), map_fn: *const fn (f32) f32) LengthValue {
|
||||
inline for (comptime bun.meta.EnumFields(@This())) |field| {
|
||||
if (field.value == @intFromEnum(this.*)) {
|
||||
return @unionInit(LengthValue, field.name, map_fn(@field(this, field.name)));
|
||||
@@ -419,8 +419,9 @@ pub const LengthValue = union(enum) {
|
||||
pub fn tryOp(
|
||||
this: *const LengthValue,
|
||||
other: *const LengthValue,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) f32,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, f32, f32) f32,
|
||||
) ?LengthValue {
|
||||
if (@intFromEnum(this.*) == @intFromEnum(other.*)) {
|
||||
inline for (bun.meta.EnumFields(LengthValue)) |field| {
|
||||
@@ -445,8 +446,9 @@ pub const LengthValue = union(enum) {
|
||||
this: *const LengthValue,
|
||||
other: *const LengthValue,
|
||||
comptime R: type,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) R,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, f32, f32) R,
|
||||
) ?R {
|
||||
if (@intFromEnum(this.*) == @intFromEnum(other.*)) {
|
||||
inline for (bun.meta.EnumFields(LengthValue)) |field| {
|
||||
@@ -751,7 +753,7 @@ pub const Length = union(enum) {
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn tryMap(this: *const Length, comptime map_fn: *const fn (f32) f32) ?Length {
|
||||
pub fn tryMap(this: *const Length, map_fn: *const fn (f32) f32) ?Length {
|
||||
return switch (this.*) {
|
||||
.value => |v| .{ .value = v.map(map_fn) },
|
||||
else => null,
|
||||
@@ -761,11 +763,12 @@ pub const Length = union(enum) {
|
||||
pub fn tryOp(
|
||||
this: *const Length,
|
||||
other: *const Length,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) f32,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, f32, f32) f32,
|
||||
) ?Length {
|
||||
if (this.* == .value and other.* == .value) {
|
||||
if (this.value.tryOp(&other.value, ctx, op_fn)) |val| return .{ .value = val };
|
||||
if (this.value.tryOp(&other.value, Ctx, ctx, op_fn)) |val| return .{ .value = val };
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
@@ -775,11 +778,12 @@ pub const Length = union(enum) {
|
||||
this: *const Length,
|
||||
other: *const Length,
|
||||
comptime R: type,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) R,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, f32, f32) R,
|
||||
) ?R {
|
||||
if (this.* == .value and other.* == .value) {
|
||||
return this.value.tryOpTo(&other.value, R, ctx, op_fn);
|
||||
return this.value.tryOpTo(&other.value, R, Ctx, ctx, op_fn);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ pub const Percentage = struct {
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn tryMap(_: *const Percentage, comptime _: *const fn (f32) f32) ?Percentage {
|
||||
pub fn tryMap(_: *const Percentage, _: *const fn (f32) f32) ?Percentage {
|
||||
// Percentages cannot be mapped because we don't know what they will resolve to.
|
||||
// For example, they might be positive or negative depending on what they are a
|
||||
// percentage of, which we don't know.
|
||||
@@ -100,8 +100,9 @@ pub const Percentage = struct {
|
||||
pub fn op(
|
||||
this: *const Percentage,
|
||||
other: *const Percentage,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) f32,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, a: f32, b: f32) f32,
|
||||
) Percentage {
|
||||
return Percentage{ .v = op_fn(ctx, this.v, other.v) };
|
||||
}
|
||||
@@ -110,8 +111,9 @@ pub const Percentage = struct {
|
||||
this: *const Percentage,
|
||||
other: *const Percentage,
|
||||
comptime R: type,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) R,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, a: f32, b: f32) R,
|
||||
) R {
|
||||
return op_fn(ctx, this.v, other.v);
|
||||
}
|
||||
@@ -119,8 +121,9 @@ pub const Percentage = struct {
|
||||
pub fn tryOp(
|
||||
this: *const Percentage,
|
||||
other: *const Percentage,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) f32,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, a: f32, b: f32) f32,
|
||||
) ?Percentage {
|
||||
return Percentage{ .v = op_fn(ctx, this.v, other.v) };
|
||||
}
|
||||
@@ -430,7 +433,7 @@ pub fn DimensionPercentage(comptime D: type) type {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn tryMap(this: *const This, comptime mapfn: *const fn (f32) f32) ?This {
|
||||
pub fn tryMap(this: *const This, mapfn: *const fn (f32) f32) ?This {
|
||||
return switch (this.*) {
|
||||
.dimension => |vv| if (css.generic.tryMap(D, &vv, mapfn)) |v| .{ .dimension = v } else null,
|
||||
else => null,
|
||||
@@ -440,10 +443,11 @@ pub fn DimensionPercentage(comptime D: type) type {
|
||||
pub fn tryOp(
|
||||
this: *const This,
|
||||
other: *const This,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) f32,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, f32, f32) f32,
|
||||
) ?This {
|
||||
if (this.* == .dimension and other.* == .dimension) return .{ .dimension = css.generic.tryOp(D, &this.dimension, &other.dimension, ctx, op_fn) orelse return null };
|
||||
if (this.* == .dimension and other.* == .dimension) return .{ .dimension = css.generic.tryOp(D, &this.dimension, &other.dimension, Ctx, ctx, op_fn) orelse return null };
|
||||
if (this.* == .percentage and other.* == .percentage) return .{ .percentage = Percentage{ .v = op_fn(ctx, this.percentage.v, other.percentage.v) } };
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -71,14 +71,14 @@ pub fn Size2D(comptime T: type) type {
|
||||
return css.implementDeepClone(@This(), this, allocator);
|
||||
}
|
||||
|
||||
pub inline fn valEql(lhs: *const T, rhs: *const T) bool {
|
||||
pub fn valEql(lhs: *const T, rhs: *const T) bool {
|
||||
return switch (T) {
|
||||
f32 => lhs.* == rhs.*,
|
||||
else => lhs.eql(rhs),
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn eql(lhs: *const @This(), rhs: *const @This()) bool {
|
||||
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
|
||||
return switch (T) {
|
||||
f32 => lhs.a == rhs.b,
|
||||
else => lhs.a.eql(&rhs.b),
|
||||
|
||||
@@ -149,7 +149,7 @@ pub const Time = union(enum) {
|
||||
return css.generic.partialCmpF32(&this.toMs(), &other.toMs());
|
||||
}
|
||||
|
||||
pub fn map(this: *const @This(), comptime map_fn: *const fn (f32) f32) Time {
|
||||
pub fn map(this: *const @This(), map_fn: *const fn (f32) f32) Time {
|
||||
return switch (this.*) {
|
||||
.seconds => Time{ .seconds = map_fn(this.seconds) },
|
||||
.milliseconds => Time{ .milliseconds = map_fn(this.milliseconds) },
|
||||
@@ -166,8 +166,9 @@ pub const Time = union(enum) {
|
||||
pub fn op(
|
||||
this: *const Time,
|
||||
other: *const Time,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) f32,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, a: f32, b: f32) f32,
|
||||
) Time {
|
||||
const self_tag: u16 = @intFromEnum(this.*);
|
||||
const other_tag: u16 = @intFromEnum(other.*);
|
||||
@@ -188,8 +189,9 @@ pub const Time = union(enum) {
|
||||
this: *const Time,
|
||||
other: *const Time,
|
||||
comptime R: type,
|
||||
ctx: anytype,
|
||||
comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) R,
|
||||
comptime Ctx: type,
|
||||
ctx: Ctx,
|
||||
op_fn: *const fn (Ctx, a: f32, b: f32) R,
|
||||
) R {
|
||||
const self_tag: u16 = @intFromEnum(this.*);
|
||||
const other_tag: u16 = @intFromEnum(other.*);
|
||||
|
||||
Reference in New Issue
Block a user