mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-23 16:07:52 +00:00
Merge remote-tracking branch 'offical/master'
This commit is contained in:
@@ -14,6 +14,14 @@ constant-time byte comparison.
|
||||
- Best-effort is make to mitigate timing side-channels on reasonable
|
||||
architectures. Architectures that are known to be unreasonable include
|
||||
but are not limited to i386, i486, and WebAssembly.
|
||||
- Implementations assume a 64-bit architecture (64-bit integer arithmetic
|
||||
is fast, and includes add-with-carry, sub-with-borrow, and full-result
|
||||
multiply).
|
||||
- Hardware sidechannels are explicitly out of scope for this package.
|
||||
Notable examples include but are not limited to:
|
||||
- Power/RF side-channels etc.
|
||||
- Fault injection attacks etc.
|
||||
- Hardware vulnerabilities ("apply mitigations or buy a new CPU").
|
||||
- The packages attempt to santize sensitive data, however this is, and
|
||||
will remain a "best-effort" implementation decision. As Thomas Pornin
|
||||
puts it "In general, such memory cleansing is a fool's quest."
|
||||
|
||||
@@ -0,0 +1,428 @@
|
||||
package _edwards25519
|
||||
|
||||
/*
|
||||
This implements the edwards25519 composite-order group, primarily for
|
||||
the purpose of implementing X25519, Ed25519, and ristretto255. Use of
|
||||
this package for other purposes is NOT RECOMMENDED.
|
||||
|
||||
See:
|
||||
- https://eprint.iacr.org/2011/368.pdf
|
||||
- https://datatracker.ietf.org/doc/html/rfc8032
|
||||
- https://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
|
||||
*/
|
||||
|
||||
import "base:intrinsics"
|
||||
import "core:crypto"
|
||||
import field "core:crypto/_fiat/field_curve25519"
|
||||
import "core:mem"
|
||||
|
||||
// Group_Element is an edwards25519 group element, as extended homogenous
|
||||
// coordinates, which represents the affine point `(x, y)` as `(X, Y, Z, T)`,
|
||||
// with the relations `x = X/Z`, `y = Y/Z`, and `x * y = T/Z`.
|
||||
//
|
||||
// d = -121665/121666 = 37095705934669439343138083508754565189542113879843219016388785533085940283555
|
||||
// a = -1
|
||||
//
|
||||
// Notes:
|
||||
// - There is considerable scope for optimization, however that
|
||||
// will not change the external API, and this is simple and reasonably
|
||||
// performant.
|
||||
// - The API delibarately makes it hard to create arbitrary group
|
||||
// elements that are not on the curve.
|
||||
// - The group element decoding routine takes the opinionated stance of
|
||||
// rejecting non-canonical encodings.
|
||||
|
||||
FE_D := field.Tight_Field_Element {
|
||||
929955233495203,
|
||||
466365720129213,
|
||||
1662059464998953,
|
||||
2033849074728123,
|
||||
1442794654840575,
|
||||
}
|
||||
@(private)
|
||||
FE_A := field.Tight_Field_Element {
|
||||
2251799813685228,
|
||||
2251799813685247,
|
||||
2251799813685247,
|
||||
2251799813685247,
|
||||
2251799813685247,
|
||||
}
|
||||
@(private)
|
||||
FE_D2 := field.Tight_Field_Element {
|
||||
1859910466990425,
|
||||
932731440258426,
|
||||
1072319116312658,
|
||||
1815898335770999,
|
||||
633789495995903,
|
||||
}
|
||||
@(private)
|
||||
GE_BASEPOINT := Group_Element {
|
||||
field.Tight_Field_Element {
|
||||
1738742601995546,
|
||||
1146398526822698,
|
||||
2070867633025821,
|
||||
562264141797630,
|
||||
587772402128613,
|
||||
},
|
||||
field.Tight_Field_Element {
|
||||
1801439850948184,
|
||||
1351079888211148,
|
||||
450359962737049,
|
||||
900719925474099,
|
||||
1801439850948198,
|
||||
},
|
||||
field.Tight_Field_Element{1, 0, 0, 0, 0},
|
||||
field.Tight_Field_Element {
|
||||
1841354044333475,
|
||||
16398895984059,
|
||||
755974180946558,
|
||||
900171276175154,
|
||||
1821297809914039,
|
||||
},
|
||||
}
|
||||
GE_IDENTITY := Group_Element {
|
||||
field.Tight_Field_Element{0, 0, 0, 0, 0},
|
||||
field.Tight_Field_Element{1, 0, 0, 0, 0},
|
||||
field.Tight_Field_Element{1, 0, 0, 0, 0},
|
||||
field.Tight_Field_Element{0, 0, 0, 0, 0},
|
||||
}
|
||||
|
||||
Group_Element :: struct {
|
||||
x: field.Tight_Field_Element,
|
||||
y: field.Tight_Field_Element,
|
||||
z: field.Tight_Field_Element,
|
||||
t: field.Tight_Field_Element,
|
||||
}
|
||||
|
||||
ge_clear :: proc "contextless" (ge: ^Group_Element) {
|
||||
mem.zero_explicit(ge, size_of(Group_Element))
|
||||
}
|
||||
|
||||
ge_set :: proc "contextless" (ge, a: ^Group_Element) {
|
||||
field.fe_set(&ge.x, &a.x)
|
||||
field.fe_set(&ge.y, &a.y)
|
||||
field.fe_set(&ge.z, &a.z)
|
||||
field.fe_set(&ge.t, &a.t)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool {
|
||||
if len(b) != 32 {
|
||||
intrinsics.trap()
|
||||
}
|
||||
b_ := transmute(^[32]byte)(raw_data(b))
|
||||
|
||||
// Do the work in a scratch element, so that ge is unchanged on
|
||||
// failure.
|
||||
tmp: Group_Element = ---
|
||||
defer ge_clear(&tmp)
|
||||
field.fe_one(&tmp.z) // Z = 1
|
||||
|
||||
// The encoding is the y-coordinate, with the x-coordinate polarity
|
||||
// (odd/even) encoded in the MSB.
|
||||
field.fe_from_bytes(&tmp.y, b_) // ignores high bit
|
||||
|
||||
// Recover the candidate x-coordinate via the curve equation:
|
||||
// x^2 = (y^2 - 1) / (d * y^2 + 1) (mod p)
|
||||
|
||||
fe_tmp := &tmp.t // Use this to store intermediaries.
|
||||
fe_one := &tmp.z
|
||||
|
||||
// x = num = y^2 - 1
|
||||
field.fe_carry_square(fe_tmp, field.fe_relax_cast(&tmp.y)) // fe_tmp = y^2
|
||||
field.fe_carry_sub(&tmp.x, fe_tmp, fe_one)
|
||||
|
||||
// den = d * y^2 + 1
|
||||
field.fe_carry_mul(fe_tmp, field.fe_relax_cast(fe_tmp), field.fe_relax_cast(&FE_D))
|
||||
field.fe_carry_add(fe_tmp, fe_tmp, fe_one)
|
||||
|
||||
// x = invsqrt(den/num)
|
||||
is_square := field.fe_carry_sqrt_ratio_m1(
|
||||
&tmp.x,
|
||||
field.fe_relax_cast(&tmp.x),
|
||||
field.fe_relax_cast(fe_tmp),
|
||||
)
|
||||
if is_square == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Pick the right x-coordinate.
|
||||
field.fe_cond_negate(&tmp.x, &tmp.x, int(b[31] >> 7))
|
||||
|
||||
// t = x * y
|
||||
field.fe_carry_mul(&tmp.t, field.fe_relax_cast(&tmp.x), field.fe_relax_cast(&tmp.y))
|
||||
|
||||
// Reject non-canonical encodings of ge.
|
||||
buf: [32]byte = ---
|
||||
field.fe_to_bytes(&buf, &tmp.y)
|
||||
buf[31] |= byte(field.fe_is_negative(&tmp.x)) << 7
|
||||
is_canonical := crypto.compare_constant_time(b, buf[:])
|
||||
|
||||
ge_cond_assign(ge, &tmp, is_canonical)
|
||||
|
||||
mem.zero_explicit(&buf, size_of(buf))
|
||||
|
||||
return is_canonical == 1
|
||||
}
|
||||
|
||||
ge_bytes :: proc "contextless" (ge: ^Group_Element, dst: []byte) {
|
||||
if len(dst) != 32 {
|
||||
intrinsics.trap()
|
||||
}
|
||||
dst_ := transmute(^[32]byte)(raw_data(dst))
|
||||
|
||||
// Convert the element to affine (x, y) representation.
|
||||
x, y, z_inv: field.Tight_Field_Element = ---, ---, ---
|
||||
field.fe_carry_inv(&z_inv, field.fe_relax_cast(&ge.z))
|
||||
field.fe_carry_mul(&x, field.fe_relax_cast(&ge.x), field.fe_relax_cast(&z_inv))
|
||||
field.fe_carry_mul(&y, field.fe_relax_cast(&ge.y), field.fe_relax_cast(&z_inv))
|
||||
|
||||
// Encode the y-coordinate.
|
||||
field.fe_to_bytes(dst_, &y)
|
||||
|
||||
// Copy the least significant bit of the x-coordinate to the most
|
||||
// significant bit of the encoded y-coordinate.
|
||||
dst_[31] |= byte((x[0] & 1) << 7)
|
||||
|
||||
field.fe_clear_vec([]^field.Tight_Field_Element{&x, &y, &z_inv})
|
||||
}
|
||||
|
||||
ge_identity :: proc "contextless" (ge: ^Group_Element) {
|
||||
field.fe_zero(&ge.x)
|
||||
field.fe_one(&ge.y)
|
||||
field.fe_one(&ge.z)
|
||||
field.fe_zero(&ge.t)
|
||||
}
|
||||
|
||||
ge_generator :: proc "contextless" (ge: ^Group_Element) {
|
||||
ge_set(ge, &GE_BASEPOINT)
|
||||
}
|
||||
|
||||
@(private)
|
||||
Addend_Group_Element :: struct {
|
||||
y2_minus_x2: field.Loose_Field_Element, // t1
|
||||
y2_plus_x2: field.Loose_Field_Element, // t3
|
||||
k_times_t2: field.Tight_Field_Element, // t4
|
||||
two_times_z2: field.Loose_Field_Element, // t5
|
||||
}
|
||||
|
||||
@(private)
|
||||
ge_addend_set :: proc "contextless" (ge_a: ^Addend_Group_Element, ge: ^Group_Element) {
|
||||
field.fe_sub(&ge_a.y2_minus_x2, &ge.y, &ge.x)
|
||||
field.fe_add(&ge_a.y2_plus_x2, &ge.y, &ge.x)
|
||||
field.fe_carry_mul(&ge_a.k_times_t2, field.fe_relax_cast(&FE_D2), field.fe_relax_cast(&ge.t))
|
||||
field.fe_add(&ge_a.two_times_z2, &ge.z, &ge.z)
|
||||
}
|
||||
|
||||
@(private)
|
||||
ge_addend_conditional_assign :: proc "contextless" (ge_a, a: ^Addend_Group_Element, ctrl: int) {
|
||||
field.fe_cond_select(&ge_a.y2_minus_x2, &ge_a.y2_minus_x2, &a.y2_minus_x2, ctrl)
|
||||
field.fe_cond_select(&ge_a.y2_plus_x2, &ge_a.y2_plus_x2, &a.y2_plus_x2, ctrl)
|
||||
field.fe_cond_select(&ge_a.k_times_t2, &ge_a.k_times_t2, &a.k_times_t2, ctrl)
|
||||
field.fe_cond_select(&ge_a.two_times_z2, &ge_a.two_times_z2, &a.two_times_z2, ctrl)
|
||||
}
|
||||
|
||||
@(private)
|
||||
Add_Scratch :: struct {
|
||||
A, B, C, D: field.Tight_Field_Element,
|
||||
E, F, G, H: field.Loose_Field_Element,
|
||||
t0, t2: field.Loose_Field_Element,
|
||||
}
|
||||
|
||||
ge_add :: proc "contextless" (ge, a, b: ^Group_Element) {
|
||||
b_: Addend_Group_Element = ---
|
||||
ge_addend_set(&b_, b)
|
||||
|
||||
scratch: Add_Scratch = ---
|
||||
ge_add_addend(ge, a, &b_, &scratch)
|
||||
|
||||
mem.zero_explicit(&b_, size_of(Addend_Group_Element))
|
||||
mem.zero_explicit(&scratch, size_of(Add_Scratch))
|
||||
}
|
||||
|
||||
@(private)
|
||||
ge_add_addend :: proc "contextless" (
|
||||
ge, a: ^Group_Element,
|
||||
b: ^Addend_Group_Element,
|
||||
scratch: ^Add_Scratch,
|
||||
) {
|
||||
// https://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3
|
||||
// Assumptions: k=2*d.
|
||||
//
|
||||
// t0 = Y1-X1
|
||||
// t1 = Y2-X2
|
||||
// A = t0*t1
|
||||
// t2 = Y1+X1
|
||||
// t3 = Y2+X2
|
||||
// B = t2*t3
|
||||
// t4 = k*T2
|
||||
// C = T1*t4
|
||||
// t5 = 2*Z2
|
||||
// D = Z1*t5
|
||||
// E = B-A
|
||||
// F = D-C
|
||||
// G = D+C
|
||||
// H = B+A
|
||||
// X3 = E*F
|
||||
// Y3 = G*H
|
||||
// T3 = E*H
|
||||
// Z3 = F*G
|
||||
//
|
||||
// In order to make the scalar multiply faster, the addend is provided
|
||||
// as a `Addend_Group_Element` with t1, t3, t4, and t5 precomputed, as
|
||||
// it is trivially obvious that those are the only values used by the
|
||||
// formula that are directly dependent on `b`, and are only dependent
|
||||
// on `b` and constants. This saves 1 sub, 2 adds, and 1 multiply,
|
||||
// each time the intermediate representation can be reused.
|
||||
|
||||
A, B, C, D := &scratch.A, &scratch.B, &scratch.C, &scratch.D
|
||||
E, F, G, H := &scratch.E, &scratch.F, &scratch.G, &scratch.H
|
||||
t0, t2 := &scratch.t0, &scratch.t2
|
||||
|
||||
field.fe_sub(t0, &a.y, &a.x)
|
||||
t1 := &b.y2_minus_x2
|
||||
field.fe_carry_mul(A, t0, t1)
|
||||
field.fe_add(t2, &a.y, &a.x)
|
||||
t3 := &b.y2_plus_x2
|
||||
field.fe_carry_mul(B, t2, t3)
|
||||
t4 := &b.k_times_t2
|
||||
field.fe_carry_mul(C, field.fe_relax_cast(&a.t), field.fe_relax_cast(t4))
|
||||
t5 := &b.two_times_z2
|
||||
field.fe_carry_mul(D, field.fe_relax_cast(&a.z), t5)
|
||||
field.fe_sub(E, B, A)
|
||||
field.fe_sub(F, D, C)
|
||||
field.fe_add(G, D, C)
|
||||
field.fe_add(H, B, A)
|
||||
field.fe_carry_mul(&ge.x, E, F)
|
||||
field.fe_carry_mul(&ge.y, G, H)
|
||||
field.fe_carry_mul(&ge.t, E, H)
|
||||
field.fe_carry_mul(&ge.z, F, G)
|
||||
}
|
||||
|
||||
@(private)
|
||||
Double_Scratch :: struct {
|
||||
A, B, C, D, G: field.Tight_Field_Element,
|
||||
t0, t2, t3: field.Tight_Field_Element,
|
||||
E, F, H: field.Loose_Field_Element,
|
||||
t1: field.Loose_Field_Element,
|
||||
}
|
||||
|
||||
ge_double :: proc "contextless" (ge, a: ^Group_Element, scratch: ^Double_Scratch = nil) {
|
||||
// https://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
|
||||
//
|
||||
// A = X1^2
|
||||
// B = Y1^2
|
||||
// t0 = Z1^2
|
||||
// C = 2*t0
|
||||
// D = a*A
|
||||
// t1 = X1+Y1
|
||||
// t2 = t1^2
|
||||
// t3 = t2-A
|
||||
// E = t3-B
|
||||
// G = D+B
|
||||
// F = G-C
|
||||
// H = D-B
|
||||
// X3 = E*F
|
||||
// Y3 = G*H
|
||||
// T3 = E*H
|
||||
// Z3 = F*G
|
||||
|
||||
sanitize, scratch := scratch == nil, scratch
|
||||
if sanitize {
|
||||
tmp: Double_Scratch = ---
|
||||
scratch = &tmp
|
||||
}
|
||||
|
||||
A, B, C, D, G := &scratch.A, &scratch.B, &scratch.C, &scratch.D, &scratch.G
|
||||
t0, t2, t3 := &scratch.t0, &scratch.t2, &scratch.t3
|
||||
E, F, H := &scratch.E, &scratch.F, &scratch.H
|
||||
t1 := &scratch.t1
|
||||
|
||||
field.fe_carry_square(A, field.fe_relax_cast(&a.x))
|
||||
field.fe_carry_square(B, field.fe_relax_cast(&a.y))
|
||||
field.fe_carry_square(t0, field.fe_relax_cast(&a.z))
|
||||
field.fe_carry_add(C, t0, t0)
|
||||
field.fe_carry_mul(D, field.fe_relax_cast(&FE_A), field.fe_relax_cast(A))
|
||||
field.fe_add(t1, &a.x, &a.y)
|
||||
field.fe_carry_square(t2, t1)
|
||||
field.fe_carry_sub(t3, t2, A)
|
||||
field.fe_sub(E, t3, B)
|
||||
field.fe_carry_add(G, D, B)
|
||||
field.fe_sub(F, G, C)
|
||||
field.fe_sub(H, D, B)
|
||||
G_ := field.fe_relax_cast(G)
|
||||
field.fe_carry_mul(&ge.x, E, F)
|
||||
field.fe_carry_mul(&ge.y, G_, H)
|
||||
field.fe_carry_mul(&ge.t, E, H)
|
||||
field.fe_carry_mul(&ge.z, F, G_)
|
||||
|
||||
if sanitize {
|
||||
mem.zero_explicit(scratch, size_of(Double_Scratch))
|
||||
}
|
||||
}
|
||||
|
||||
ge_negate :: proc "contextless" (ge, a: ^Group_Element) {
|
||||
field.fe_carry_opp(&ge.x, &a.x)
|
||||
field.fe_set(&ge.y, &a.y)
|
||||
field.fe_set(&ge.z, &a.z)
|
||||
field.fe_carry_opp(&ge.t, &a.t)
|
||||
}
|
||||
|
||||
ge_cond_negate :: proc "contextless" (ge, a: ^Group_Element, ctrl: int) {
|
||||
tmp: Group_Element = ---
|
||||
ge_negate(&tmp, a)
|
||||
ge_cond_assign(ge, &tmp, ctrl)
|
||||
|
||||
ge_clear(&tmp)
|
||||
}
|
||||
|
||||
ge_cond_assign :: proc "contextless" (ge, a: ^Group_Element, ctrl: int) {
|
||||
field.fe_cond_assign(&ge.x, &a.x, ctrl)
|
||||
field.fe_cond_assign(&ge.y, &a.y, ctrl)
|
||||
field.fe_cond_assign(&ge.z, &a.z, ctrl)
|
||||
field.fe_cond_assign(&ge.t, &a.t, ctrl)
|
||||
}
|
||||
|
||||
ge_cond_select :: proc "contextless" (ge, a, b: ^Group_Element, ctrl: int) {
|
||||
field.fe_cond_select(&ge.x, &a.x, &b.x, ctrl)
|
||||
field.fe_cond_select(&ge.y, &a.y, &b.y, ctrl)
|
||||
field.fe_cond_select(&ge.z, &a.z, &b.z, ctrl)
|
||||
field.fe_cond_select(&ge.t, &a.t, &b.t, ctrl)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
ge_equal :: proc "contextless" (a, b: ^Group_Element) -> int {
|
||||
// (x, y) ?= (x', y') -> (X/Z, Y/Z) ?= (X'/Z', Y'/Z')
|
||||
// X/Z ?= X'/Z', Y/Z ?= Y'/Z' -> X*Z' ?= X'*Z, Y*Z' ?= Y'*Z
|
||||
ax_bz, bx_az, ay_bz, by_az: field.Tight_Field_Element = ---, ---, ---, ---
|
||||
field.fe_carry_mul(&ax_bz, field.fe_relax_cast(&a.x), field.fe_relax_cast(&b.z))
|
||||
field.fe_carry_mul(&bx_az, field.fe_relax_cast(&b.x), field.fe_relax_cast(&a.z))
|
||||
field.fe_carry_mul(&ay_bz, field.fe_relax_cast(&a.y), field.fe_relax_cast(&b.z))
|
||||
field.fe_carry_mul(&by_az, field.fe_relax_cast(&b.y), field.fe_relax_cast(&a.z))
|
||||
|
||||
ret := field.fe_equal(&ax_bz, &bx_az) & field.fe_equal(&ay_bz, &by_az)
|
||||
|
||||
field.fe_clear_vec([]^field.Tight_Field_Element{&ax_bz, &ay_bz, &bx_az, &by_az})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
ge_is_small_order :: proc "contextless" (ge: ^Group_Element) -> bool {
|
||||
tmp: Group_Element = ---
|
||||
ge_double(&tmp, ge)
|
||||
ge_double(&tmp, &tmp)
|
||||
ge_double(&tmp, &tmp)
|
||||
return ge_equal(&tmp, &GE_IDENTITY) == 1
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
ge_in_prime_order_subgroup_vartime :: proc "contextless" (ge: ^Group_Element) -> bool {
|
||||
// This is currently *very* expensive. The faster method would be
|
||||
// something like (https://eprint.iacr.org/2022/1164.pdf), however
|
||||
// that is a ~50% speedup, and a lot of added complexity for something
|
||||
// that is better solved by "just use ristretto255".
|
||||
tmp: Group_Element = ---
|
||||
_ge_scalarmult(&tmp, ge, &SC_ELL, true)
|
||||
return ge_equal(&tmp, &GE_IDENTITY) == 1
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package _edwards25519
|
||||
|
||||
import "base:intrinsics"
|
||||
import field "core:crypto/_fiat/field_scalar25519"
|
||||
import "core:mem"
|
||||
|
||||
Scalar :: field.Montgomery_Domain_Field_Element
|
||||
|
||||
// WARNING: This is non-canonical and only to be used when checking if
|
||||
// a group element is on the prime-order subgroup.
|
||||
@(private)
|
||||
SC_ELL := field.Non_Montgomery_Domain_Field_Element {
|
||||
field.ELL[0],
|
||||
field.ELL[1],
|
||||
field.ELL[2],
|
||||
field.ELL[3],
|
||||
}
|
||||
|
||||
sc_set_u64 :: proc "contextless" (sc: ^Scalar, i: u64) {
|
||||
tmp := field.Non_Montgomery_Domain_Field_Element{i, 0, 0, 0}
|
||||
field.fe_to_montgomery(sc, &tmp)
|
||||
|
||||
mem.zero_explicit(&tmp, size_of(tmp))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
sc_set_bytes :: proc "contextless" (sc: ^Scalar, b: []byte) -> bool {
|
||||
if len(b) != 32 {
|
||||
intrinsics.trap()
|
||||
}
|
||||
b_ := transmute(^[32]byte)(raw_data(b))
|
||||
return field.fe_from_bytes(sc, b_)
|
||||
}
|
||||
|
||||
sc_set_bytes_rfc8032 :: proc "contextless" (sc: ^Scalar, b: []byte) {
|
||||
if len(b) != 32 {
|
||||
intrinsics.trap()
|
||||
}
|
||||
b_ := transmute(^[32]byte)(raw_data(b))
|
||||
field.fe_from_bytes_rfc8032(sc, b_)
|
||||
}
|
||||
|
||||
sc_clear :: proc "contextless" (sc: ^Scalar) {
|
||||
mem.zero_explicit(sc, size_of(Scalar))
|
||||
}
|
||||
|
||||
sc_set :: field.fe_set
|
||||
sc_set_bytes_wide :: field.fe_from_bytes_wide
|
||||
sc_bytes :: field.fe_to_bytes
|
||||
|
||||
sc_zero :: field.fe_zero
|
||||
sc_one :: field.fe_one
|
||||
|
||||
sc_add :: field.fe_add
|
||||
sc_sub :: field.fe_sub
|
||||
sc_negate :: field.fe_opp
|
||||
sc_mul :: field.fe_mul
|
||||
sc_square :: field.fe_square
|
||||
|
||||
sc_cond_assign :: field.fe_cond_assign
|
||||
sc_equal :: field.fe_equal
|
||||
@@ -0,0 +1,288 @@
|
||||
package _edwards25519
|
||||
|
||||
import field "core:crypto/_fiat/field_scalar25519"
|
||||
import "core:math/bits"
|
||||
import "core:mem"
|
||||
|
||||
// GE_BASEPOINT_TABLE is 1 * G, ... 15 * G, in precomputed format.
|
||||
//
|
||||
// Note: When generating, the values were reduced to Tight_Field_Element
|
||||
// ranges, even though that is not required.
|
||||
@(private)
|
||||
GE_BASEPOINT_TABLE := Multiply_Table {
|
||||
{
|
||||
{62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585},
|
||||
{1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563},
|
||||
{301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142},
|
||||
{2, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
{1519297034332653, 1098796920435767, 1823476547744119, 808144629470969, 2110930855619772},
|
||||
{338005982828284, 1667856962156925, 100399270107451, 1604566703601691, 1950338038771369},
|
||||
{1920505767731247, 1443759578976892, 1659852098357048, 1484431291070208, 275018744912646},
|
||||
{763163817085987, 2195095074806923, 2167883174351839, 1868059999999762, 911071066608705},
|
||||
},
|
||||
{
|
||||
{960627541894068, 1314966688943942, 1126875971034044, 2059608312958945, 605975666152586},
|
||||
{1714478358025626, 2209607666607510, 1600912834284834, 496072478982142, 481970031861896},
|
||||
{851735079403194, 1088965826757164, 141569479297499, 602804610059257, 2004026468601520},
|
||||
{197585529552380, 324719066578543, 564481854250498, 1173818332764578, 35452976395676},
|
||||
},
|
||||
{
|
||||
{1152980410747203, 2196804280851952, 25745194962557, 1915167295473129, 1266299690309224},
|
||||
{809905889679060, 979732230071345, 1509972345538142, 188492426534402, 818965583123815},
|
||||
{997685409185036, 1451818320876327, 2126681166774509, 2000509606057528, 235432372486854},
|
||||
{887734189279642, 1460338685162044, 877378220074262, 102436391401299, 153369156847490},
|
||||
},
|
||||
{
|
||||
{2056621900836770, 1821657694132497, 1627986892909426, 1163363868678833, 1108873376459226},
|
||||
{1187697490593623, 1066539945237335, 885654531892000, 1357534489491782, 359370291392448},
|
||||
{1509033452137525, 1305318174298508, 613642471748944, 1987256352550234, 1044283663101541},
|
||||
{220105720697037, 387661783287620, 328296827867762, 360035589590664, 795213236824054},
|
||||
},
|
||||
{
|
||||
{1820794733038396, 1612235121681074, 757405923441402, 1094031020892801, 231025333128907},
|
||||
{1639067873254194, 1484176557946322, 300800382144789, 1329915446659183, 1211704578730455},
|
||||
{641900794791527, 1711751746971612, 179044712319955, 576455585963824, 1852617592509865},
|
||||
{743549047192397, 685091042550147, 1952415336873496, 1965124675654685, 513364998442917},
|
||||
},
|
||||
{
|
||||
{1004557076870448, 1762911374844520, 1330807633622723, 384072910939787, 953849032243810},
|
||||
{2178275058221458, 257933183722891, 376684351537894, 2010189102001786, 1981824297484148},
|
||||
{1332915663881114, 1286540505502549, 1741691283561518, 977214932156314, 1764059494778091},
|
||||
{429702949064027, 1368332611650677, 2019867176450999, 2212258376161746, 526160996742554},
|
||||
},
|
||||
{
|
||||
{2098932988258576, 2203688382075948, 2120400160059479, 1748488020948146, 1203264167282624},
|
||||
{677131386735829, 1850249298025188, 672782146532031, 2144145693078904, 2088656272813787},
|
||||
{1065622343976192, 1573853211848116, 223560413590068, 333846833073379, 27832122205830},
|
||||
{1781008836504573, 917619542051793, 544322748939913, 882577394308384, 1720521246471195},
|
||||
},
|
||||
{
|
||||
{660120928379860, 2081944024858618, 1878411111349191, 424587356517195, 2111317439894005},
|
||||
{1834193977811532, 1864164086863319, 797334633289424, 150410812403062, 2085177078466389},
|
||||
{1438117271371866, 783915531014482, 388731514584658, 292113935417795, 1945855002546714},
|
||||
{1678140823166658, 679103239148744, 614102761596238, 1052962498997885, 1863983323810390},
|
||||
},
|
||||
{
|
||||
{1690309392496233, 1116333140326275, 1377242323631039, 717196888780674, 82724646713353},
|
||||
{1722370213432106, 74265192976253, 264239578448472, 1714909985012994, 2216984958602173},
|
||||
{2010482366920922, 1294036471886319, 566466395005815, 1631955803657320, 1751698647538458},
|
||||
{1073230604155753, 1159087041338551, 1664057985455483, 127472702826203, 1339591128522371},
|
||||
},
|
||||
{
|
||||
{478053307175577, 2179515791720985, 21146535423512, 1831683844029536, 462805561553981},
|
||||
{1945267486565588, 1298536818409655, 2214511796262989, 1904981051429012, 252904800782086},
|
||||
{268945954671210, 222740425595395, 1208025911856230, 1080418823003555, 75929831922483},
|
||||
{1884784014268948, 643868448202966, 978736549726821, 46385971089796, 1296884812292320},
|
||||
},
|
||||
{
|
||||
{1861159462859103, 7077532564710, 963010365896826, 1938780006785270, 766241051941647},
|
||||
{1778966986051906, 1713995999765361, 1394565822271816, 1366699246468722, 1213407027149475},
|
||||
{1978989286560907, 2135084162045594, 1951565508865477, 671788336314416, 293123929458176},
|
||||
{902608944504080, 2167765718046481, 1285718473078022, 1222562171329269, 492109027844479},
|
||||
},
|
||||
{
|
||||
{1820807832746213, 1029220580458586, 1101997555432203, 1039081975563572, 202477981158221},
|
||||
{1866134980680205, 2222325502763386, 1830284629571201, 1046966214478970, 418381946936795},
|
||||
{1783460633291322, 1719505443254998, 1810489639976220, 877049370713018, 2187801198742619},
|
||||
{197118243000763, 305493867565736, 518814410156522, 1656246186645170, 901894734874934},
|
||||
},
|
||||
{
|
||||
{225454942125915, 478410476654509, 600524586037746, 643450007230715, 1018615928259319},
|
||||
{1733330584845708, 881092297970296, 507039890129464, 496397090721598, 2230888519577628},
|
||||
{690155664737246, 1010454785646677, 753170144375012, 1651277613844874, 1622648796364156},
|
||||
{1321310321891618, 1089655277873603, 235891750867089, 815878279563688, 1709264240047556},
|
||||
},
|
||||
{
|
||||
{805027036551342, 1387174275567452, 1156538511461704, 1465897486692171, 1208567094120903},
|
||||
{2228417017817483, 202885584970535, 2182114782271881, 2077405042592934, 1029684358182774},
|
||||
{460447547653983, 627817697755692, 524899434670834, 1228019344939427, 740684787777653},
|
||||
{849757462467675, 447476306919899, 422618957298818, 302134659227815, 675831828440895},
|
||||
},
|
||||
}
|
||||
|
||||
ge_scalarmult :: proc "contextless" (ge, p: ^Group_Element, sc: ^Scalar) {
|
||||
tmp: field.Non_Montgomery_Domain_Field_Element
|
||||
field.fe_from_montgomery(&tmp, sc)
|
||||
|
||||
_ge_scalarmult(ge, p, &tmp)
|
||||
|
||||
mem.zero_explicit(&tmp, size_of(tmp))
|
||||
}
|
||||
|
||||
ge_scalarmult_basepoint :: proc "contextless" (ge: ^Group_Element, sc: ^Scalar) {
|
||||
// Something like the comb method from "Fast and compact elliptic-curve
|
||||
// cryptography" Section 3.3, would be more performant, but more
|
||||
// complex.
|
||||
//
|
||||
// - https://eprint.iacr.org/2012/309
|
||||
ge_scalarmult(ge, &GE_BASEPOINT, sc)
|
||||
}
|
||||
|
||||
ge_scalarmult_vartime :: proc "contextless" (ge, p: ^Group_Element, sc: ^Scalar) {
|
||||
tmp: field.Non_Montgomery_Domain_Field_Element
|
||||
field.fe_from_montgomery(&tmp, sc)
|
||||
|
||||
_ge_scalarmult(ge, p, &tmp, true)
|
||||
}
|
||||
|
||||
ge_double_scalarmult_basepoint_vartime :: proc "contextless" (
|
||||
ge: ^Group_Element,
|
||||
a: ^Scalar,
|
||||
A: ^Group_Element,
|
||||
b: ^Scalar,
|
||||
) {
|
||||
// Strauss-Shamir, commonly referred to as the "Shamir trick",
|
||||
// saves half the doublings, relative to doing this the naive way.
|
||||
//
|
||||
// ABGLSV-Pornin (https://eprint.iacr.org/2020/454) is faster,
|
||||
// but significantly more complex, and has incompatibilities with
|
||||
// mixed-order group elements.
|
||||
|
||||
tmp_add: Add_Scratch = ---
|
||||
tmp_addend: Addend_Group_Element = ---
|
||||
tmp_dbl: Double_Scratch = ---
|
||||
tmp: Group_Element = ---
|
||||
|
||||
A_tbl: Multiply_Table = ---
|
||||
mul_tbl_set(&A_tbl, A, &tmp_add)
|
||||
|
||||
sc_a, sc_b: field.Non_Montgomery_Domain_Field_Element
|
||||
field.fe_from_montgomery(&sc_a, a)
|
||||
field.fe_from_montgomery(&sc_b, b)
|
||||
|
||||
ge_identity(&tmp)
|
||||
for i := 31; i >= 0; i = i - 1 {
|
||||
limb := i / 8
|
||||
shift := uint(i & 7) * 8
|
||||
|
||||
limb_byte_a := sc_a[limb] >> shift
|
||||
limb_byte_b := sc_b[limb] >> shift
|
||||
|
||||
hi_a, lo_a := (limb_byte_a >> 4) & 0x0f, limb_byte_a & 0x0f
|
||||
hi_b, lo_b := (limb_byte_b >> 4) & 0x0f, limb_byte_b & 0x0f
|
||||
|
||||
if i != 31 {
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
}
|
||||
mul_tbl_add(&tmp, &A_tbl, hi_a, &tmp_add, &tmp_addend, true)
|
||||
mul_tbl_add(&tmp, &GE_BASEPOINT_TABLE, hi_b, &tmp_add, &tmp_addend, true)
|
||||
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
mul_tbl_add(&tmp, &A_tbl, lo_a, &tmp_add, &tmp_addend, true)
|
||||
mul_tbl_add(&tmp, &GE_BASEPOINT_TABLE, lo_b, &tmp_add, &tmp_addend, true)
|
||||
}
|
||||
|
||||
ge_set(ge, &tmp)
|
||||
}
|
||||
|
||||
@(private)
|
||||
_ge_scalarmult :: proc "contextless" (
|
||||
ge, p: ^Group_Element,
|
||||
sc: ^field.Non_Montgomery_Domain_Field_Element,
|
||||
unsafe_is_vartime := false,
|
||||
) {
|
||||
// Do the simplest possible thing that works and provides adequate,
|
||||
// performance, which is windowed add-then-multiply.
|
||||
|
||||
tmp_add: Add_Scratch = ---
|
||||
tmp_addend: Addend_Group_Element = ---
|
||||
tmp_dbl: Double_Scratch = ---
|
||||
tmp: Group_Element = ---
|
||||
|
||||
p_tbl: Multiply_Table = ---
|
||||
mul_tbl_set(&p_tbl, p, &tmp_add)
|
||||
|
||||
ge_identity(&tmp)
|
||||
for i := 31; i >= 0; i = i - 1 {
|
||||
limb := i / 8
|
||||
shift := uint(i & 7) * 8
|
||||
limb_byte := sc[limb] >> shift
|
||||
|
||||
hi, lo := (limb_byte >> 4) & 0x0f, limb_byte & 0x0f
|
||||
|
||||
if i != 31 {
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
}
|
||||
mul_tbl_add(&tmp, &p_tbl, hi, &tmp_add, &tmp_addend, unsafe_is_vartime)
|
||||
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
ge_double(&tmp, &tmp, &tmp_dbl)
|
||||
mul_tbl_add(&tmp, &p_tbl, lo, &tmp_add, &tmp_addend, unsafe_is_vartime)
|
||||
}
|
||||
|
||||
ge_set(ge, &tmp)
|
||||
|
||||
if !unsafe_is_vartime {
|
||||
ge_clear(&tmp)
|
||||
mem.zero_explicit(&tmp_add, size_of(Add_Scratch))
|
||||
mem.zero_explicit(&tmp_addend, size_of(Addend_Group_Element))
|
||||
mem.zero_explicit(&tmp_dbl, size_of(Double_Scratch))
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
Multiply_Table :: [15]Addend_Group_Element // 0 = inf, which is implicit.
|
||||
|
||||
@(private)
|
||||
mul_tbl_set :: proc "contextless" (
|
||||
tbl: ^Multiply_Table,
|
||||
ge: ^Group_Element,
|
||||
tmp_add: ^Add_Scratch,
|
||||
) {
|
||||
tmp: Group_Element = ---
|
||||
ge_set(&tmp, ge)
|
||||
|
||||
ge_addend_set(&tbl[0], ge)
|
||||
for i := 1; i < 15; i = i + 1 {
|
||||
ge_add_addend(&tmp, &tmp, &tbl[0], tmp_add)
|
||||
ge_addend_set(&tbl[i], &tmp)
|
||||
}
|
||||
|
||||
ge_clear(&tmp)
|
||||
}
|
||||
|
||||
@(private)
|
||||
mul_tbl_add :: proc "contextless" (
|
||||
ge: ^Group_Element,
|
||||
tbl: ^Multiply_Table,
|
||||
idx: u64,
|
||||
tmp_add: ^Add_Scratch,
|
||||
tmp_addend: ^Addend_Group_Element,
|
||||
unsafe_is_vartime: bool,
|
||||
) {
|
||||
// Variable time lookup, with the addition omitted entirely if idx == 0.
|
||||
if unsafe_is_vartime {
|
||||
// Skip adding the point at infinity.
|
||||
if idx != 0 {
|
||||
ge_add_addend(ge, ge, &tbl[idx - 1], tmp_add)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Constant time lookup.
|
||||
tmp_addend^ = {
|
||||
// Point at infinity (0, 1, 1, 0) in precomputed form
|
||||
{1, 0, 0, 0, 0}, // y - x
|
||||
{1, 0, 0, 0, 0}, // y + x
|
||||
{0, 0, 0, 0, 0}, // t * 2d
|
||||
{2, 0, 0, 0, 0}, // z * 2
|
||||
}
|
||||
for i := u64(1); i < 16; i = i + 1 {
|
||||
_, ctrl := bits.sub_u64(0, (i ~ idx), 0)
|
||||
ge_addend_conditional_assign(tmp_addend, &tbl[i - 1], int(~ctrl) & 1)
|
||||
}
|
||||
ge_add_addend(ge, ge, tmp_addend, tmp_add)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ package fiat
|
||||
u1 :: distinct u8
|
||||
i1 :: distinct i8
|
||||
|
||||
@(optimization_mode="none")
|
||||
@(optimization_mode = "none")
|
||||
cmovznz_u64 :: proc "contextless" (arg1: u1, arg2, arg3: u64) -> (out1: u64) {
|
||||
x1 := (u64(arg1) * 0xffffffffffffffff)
|
||||
x2 := ((x1 & arg3) | ((~x1) & arg2))
|
||||
@@ -17,7 +17,7 @@ cmovznz_u64 :: proc "contextless" (arg1: u1, arg2, arg3: u64) -> (out1: u64) {
|
||||
return
|
||||
}
|
||||
|
||||
@(optimization_mode="none")
|
||||
@(optimization_mode = "none")
|
||||
cmovznz_u32 :: proc "contextless" (arg1: u1, arg2, arg3: u32) -> (out1: u32) {
|
||||
x1 := (u32(arg1) * 0xffffffff)
|
||||
x2 := ((x1 & arg3) | ((~x1) & arg2))
|
||||
|
||||
@@ -3,14 +3,32 @@ package field_curve25519
|
||||
import "core:crypto"
|
||||
import "core:mem"
|
||||
|
||||
fe_relax_cast :: #force_inline proc "contextless" (arg1: ^Tight_Field_Element) -> ^Loose_Field_Element {
|
||||
fe_relax_cast :: #force_inline proc "contextless" (
|
||||
arg1: ^Tight_Field_Element,
|
||||
) -> ^Loose_Field_Element {
|
||||
return transmute(^Loose_Field_Element)(arg1)
|
||||
}
|
||||
|
||||
fe_tighten_cast :: #force_inline proc "contextless" (arg1: ^Loose_Field_Element) -> ^Tight_Field_Element {
|
||||
fe_tighten_cast :: #force_inline proc "contextless" (
|
||||
arg1: ^Loose_Field_Element,
|
||||
) -> ^Tight_Field_Element {
|
||||
return transmute(^Tight_Field_Element)(arg1)
|
||||
}
|
||||
|
||||
fe_clear :: proc "contextless" (
|
||||
arg1: $T,
|
||||
) where T == ^Tight_Field_Element || T == ^Loose_Field_Element {
|
||||
mem.zero_explicit(arg1, size_of(arg1^))
|
||||
}
|
||||
|
||||
fe_clear_vec :: proc "contextless" (
|
||||
arg1: $T,
|
||||
) where T == []^Tight_Field_Element || T == []^Loose_Field_Element {
|
||||
for fe in arg1 {
|
||||
fe_clear(fe)
|
||||
}
|
||||
}
|
||||
|
||||
fe_from_bytes :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^[32]byte) {
|
||||
// Ignore the unused bit by copying the input and masking the bit off
|
||||
// prior to deserialization.
|
||||
@@ -23,12 +41,25 @@ fe_from_bytes :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^[32]byte
|
||||
mem.zero_explicit(&tmp1, size_of(tmp1))
|
||||
}
|
||||
|
||||
fe_is_negative :: proc "contextless" (arg1: ^Tight_Field_Element) -> int {
|
||||
tmp1: [32]byte = ---
|
||||
|
||||
fe_to_bytes(&tmp1, arg1)
|
||||
ret := tmp1[0] & 1
|
||||
|
||||
mem.zero_explicit(&tmp1, size_of(tmp1))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
fe_equal :: proc "contextless" (arg1, arg2: ^Tight_Field_Element) -> int {
|
||||
tmp2: [32]byte = ---
|
||||
tmp1, tmp2: [32]byte = ---, ---
|
||||
|
||||
fe_to_bytes(&tmp1, arg1)
|
||||
fe_to_bytes(&tmp2, arg2)
|
||||
ret := fe_equal_bytes(arg1, &tmp2)
|
||||
ret := crypto.compare_constant_time(tmp1[:], tmp2[:])
|
||||
|
||||
mem.zero_explicit(&tmp1, size_of(tmp1))
|
||||
mem.zero_explicit(&tmp2, size_of(tmp2))
|
||||
|
||||
return ret
|
||||
@@ -46,7 +77,11 @@ fe_equal_bytes :: proc "contextless" (arg1: ^Tight_Field_Element, arg2: ^[32]byt
|
||||
return ret
|
||||
}
|
||||
|
||||
fe_carry_pow2k :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element, arg2: uint) {
|
||||
fe_carry_pow2k :: proc "contextless" (
|
||||
out1: ^Tight_Field_Element,
|
||||
arg1: ^Loose_Field_Element,
|
||||
arg2: uint,
|
||||
) {
|
||||
// Special case: `arg1^(2 * 0) = 1`, though this should never happen.
|
||||
if arg2 == 0 {
|
||||
fe_one(out1)
|
||||
@@ -54,27 +89,46 @@ fe_carry_pow2k :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element,
|
||||
}
|
||||
|
||||
fe_carry_square(out1, arg1)
|
||||
for _ in 1..<arg2 {
|
||||
for _ in 1 ..< arg2 {
|
||||
fe_carry_square(out1, fe_relax_cast(out1))
|
||||
}
|
||||
}
|
||||
|
||||
fe_carry_add :: #force_inline proc "contextless" (out1, arg1, arg2: ^Tight_Field_Element) {
|
||||
fe_add(fe_relax_cast(out1), arg1, arg2)
|
||||
fe_carry(out1, fe_relax_cast(out1))
|
||||
}
|
||||
|
||||
fe_carry_sub :: #force_inline proc "contextless" (out1, arg1, arg2: ^Tight_Field_Element) {
|
||||
fe_sub(fe_relax_cast(out1), arg1, arg2)
|
||||
fe_carry(out1, fe_relax_cast(out1))
|
||||
}
|
||||
|
||||
fe_carry_opp :: #force_inline proc "contextless" (out1, arg1: ^Tight_Field_Element) {
|
||||
fe_opp(fe_relax_cast(out1), arg1)
|
||||
fe_carry(out1, fe_relax_cast(out1))
|
||||
}
|
||||
|
||||
fe_carry_invsqrt :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) -> int {
|
||||
// Inverse square root taken from Monocypher.
|
||||
fe_carry_abs :: #force_inline proc "contextless" (out1, arg1: ^Tight_Field_Element) {
|
||||
fe_cond_negate(out1, arg1, fe_is_negative(arg1))
|
||||
}
|
||||
|
||||
fe_carry_sqrt_ratio_m1 :: proc "contextless" (
|
||||
out1: ^Tight_Field_Element,
|
||||
arg1: ^Loose_Field_Element, // u
|
||||
arg2: ^Loose_Field_Element, // v
|
||||
) -> int {
|
||||
// SQRT_RATIO_M1(u, v) from RFC 9496 - 4.2, based on the inverse
|
||||
// square root from Monocypher.
|
||||
|
||||
w: Tight_Field_Element = ---
|
||||
fe_carry_mul(&w, arg1, arg2) // u * v
|
||||
|
||||
// r = tmp1 = u * w^((p-5)/8)
|
||||
tmp1, tmp2, tmp3: Tight_Field_Element = ---, ---, ---
|
||||
|
||||
// t0 = x^((p-5)/8)
|
||||
// Can be achieved with a simple double & add ladder,
|
||||
// but it would be slower.
|
||||
fe_carry_pow2k(&tmp1, arg1, 1)
|
||||
fe_carry_pow2k(&tmp1, fe_relax_cast(&w), 1)
|
||||
fe_carry_pow2k(&tmp2, fe_relax_cast(&tmp1), 2)
|
||||
fe_carry_mul(&tmp2, arg1, fe_relax_cast(&tmp2))
|
||||
fe_carry_mul(&tmp2, fe_relax_cast(&w), fe_relax_cast(&tmp2))
|
||||
fe_carry_mul(&tmp1, fe_relax_cast(&tmp1), fe_relax_cast(&tmp2))
|
||||
fe_carry_pow2k(&tmp1, fe_relax_cast(&tmp1), 1)
|
||||
fe_carry_mul(&tmp1, fe_relax_cast(&tmp2), fe_relax_cast(&tmp1))
|
||||
@@ -93,46 +147,121 @@ fe_carry_invsqrt :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element
|
||||
fe_carry_pow2k(&tmp2, fe_relax_cast(&tmp2), 50)
|
||||
fe_carry_mul(&tmp1, fe_relax_cast(&tmp2), fe_relax_cast(&tmp1))
|
||||
fe_carry_pow2k(&tmp1, fe_relax_cast(&tmp1), 2)
|
||||
fe_carry_mul(&tmp1, fe_relax_cast(&tmp1), arg1)
|
||||
fe_carry_mul(&tmp1, fe_relax_cast(&tmp1), fe_relax_cast(&w)) // w^((p-5)/8)
|
||||
|
||||
// quartic = x^((p-1)/4)
|
||||
quartic := &tmp2
|
||||
fe_carry_square(quartic, fe_relax_cast(&tmp1))
|
||||
fe_carry_mul(quartic, fe_relax_cast(quartic), arg1)
|
||||
fe_carry_mul(&tmp1, fe_relax_cast(&tmp1), arg1) // u * w^((p-5)/8)
|
||||
|
||||
// Serialize quartic once to save on repeated serialization/sanitization.
|
||||
quartic_buf: [32]byte = ---
|
||||
fe_to_bytes(&quartic_buf, quartic)
|
||||
check := &tmp3
|
||||
// Serialize `check` once to save on repeated serialization.
|
||||
r, check := &tmp1, &tmp2
|
||||
b: [32]byte = ---
|
||||
fe_carry_square(check, fe_relax_cast(r))
|
||||
fe_carry_mul(check, fe_relax_cast(check), arg2) // check * v
|
||||
fe_to_bytes(&b, check)
|
||||
|
||||
fe_one(check)
|
||||
p1 := fe_equal_bytes(check, &quartic_buf)
|
||||
fe_carry_opp(check, check)
|
||||
m1 := fe_equal_bytes(check, &quartic_buf)
|
||||
fe_carry_opp(check, &SQRT_M1)
|
||||
ms := fe_equal_bytes(check, &quartic_buf)
|
||||
u, neg_u, neg_u_i := &tmp3, &w, check
|
||||
fe_carry(u, arg1)
|
||||
fe_carry_opp(neg_u, u)
|
||||
fe_carry_mul(neg_u_i, fe_relax_cast(neg_u), fe_relax_cast(&FE_SQRT_M1))
|
||||
|
||||
// if quartic == -1 or sqrt(-1)
|
||||
// then isr = x^((p-1)/4) * sqrt(-1)
|
||||
// else isr = x^((p-1)/4)
|
||||
fe_carry_mul(out1, fe_relax_cast(&tmp1), fe_relax_cast(&SQRT_M1))
|
||||
fe_cond_assign(out1, &tmp1, (m1|ms) ~ 1)
|
||||
correct_sign_sqrt := fe_equal_bytes(u, &b)
|
||||
flipped_sign_sqrt := fe_equal_bytes(neg_u, &b)
|
||||
flipped_sign_sqrt_i := fe_equal_bytes(neg_u_i, &b)
|
||||
|
||||
mem.zero_explicit(&tmp1, size_of(tmp1))
|
||||
mem.zero_explicit(&tmp2, size_of(tmp2))
|
||||
mem.zero_explicit(&tmp3, size_of(tmp3))
|
||||
mem.zero_explicit(&quartic_buf, size_of(quartic_buf))
|
||||
r_prime := check
|
||||
fe_carry_mul(r_prime, fe_relax_cast(r), fe_relax_cast(&FE_SQRT_M1))
|
||||
fe_cond_assign(r, r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i)
|
||||
|
||||
return p1 | m1
|
||||
// Pick the non-negative square root.
|
||||
fe_carry_abs(out1, r)
|
||||
|
||||
fe_clear_vec([]^Tight_Field_Element{&w, &tmp1, &tmp2, &tmp3})
|
||||
mem.zero_explicit(&b, size_of(b))
|
||||
|
||||
return correct_sign_sqrt | flipped_sign_sqrt
|
||||
}
|
||||
|
||||
fe_carry_inv :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
|
||||
fe_carry_inv :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
|
||||
tmp1: Tight_Field_Element
|
||||
|
||||
fe_carry_square(&tmp1, arg1)
|
||||
_ = fe_carry_invsqrt(&tmp1, fe_relax_cast(&tmp1))
|
||||
_ = fe_carry_sqrt_ratio_m1(&tmp1, fe_relax_cast(&FE_ONE), fe_relax_cast(&tmp1))
|
||||
fe_carry_square(&tmp1, fe_relax_cast(&tmp1))
|
||||
fe_carry_mul(out1, fe_relax_cast(&tmp1), arg1)
|
||||
|
||||
mem.zero_explicit(&tmp1, size_of(tmp1))
|
||||
fe_clear(&tmp1)
|
||||
}
|
||||
|
||||
fe_zero :: proc "contextless" (out1: ^Tight_Field_Element) {
|
||||
out1[0] = 0
|
||||
out1[1] = 0
|
||||
out1[2] = 0
|
||||
out1[3] = 0
|
||||
out1[4] = 0
|
||||
}
|
||||
|
||||
fe_one :: proc "contextless" (out1: ^Tight_Field_Element) {
|
||||
out1[0] = 1
|
||||
out1[1] = 0
|
||||
out1[2] = 0
|
||||
out1[3] = 0
|
||||
out1[4] = 0
|
||||
}
|
||||
|
||||
fe_set :: proc "contextless" (out1, arg1: ^Tight_Field_Element) {
|
||||
x1 := arg1[0]
|
||||
x2 := arg1[1]
|
||||
x3 := arg1[2]
|
||||
x4 := arg1[3]
|
||||
x5 := arg1[4]
|
||||
out1[0] = x1
|
||||
out1[1] = x2
|
||||
out1[2] = x3
|
||||
out1[3] = x4
|
||||
out1[4] = x5
|
||||
}
|
||||
|
||||
@(optimization_mode = "none")
|
||||
fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: int) {
|
||||
mask := (u64(arg1) * 0xffffffffffffffff)
|
||||
x := (out1[0] ~ out2[0]) & mask
|
||||
x1, y1 := out1[0] ~ x, out2[0] ~ x
|
||||
x = (out1[1] ~ out2[1]) & mask
|
||||
x2, y2 := out1[1] ~ x, out2[1] ~ x
|
||||
x = (out1[2] ~ out2[2]) & mask
|
||||
x3, y3 := out1[2] ~ x, out2[2] ~ x
|
||||
x = (out1[3] ~ out2[3]) & mask
|
||||
x4, y4 := out1[3] ~ x, out2[3] ~ x
|
||||
x = (out1[4] ~ out2[4]) & mask
|
||||
x5, y5 := out1[4] ~ x, out2[4] ~ x
|
||||
out1[0], out2[0] = x1, y1
|
||||
out1[1], out2[1] = x2, y2
|
||||
out1[2], out2[2] = x3, y3
|
||||
out1[3], out2[3] = x4, y4
|
||||
out1[4], out2[4] = x5, y5
|
||||
}
|
||||
|
||||
@(optimization_mode = "none")
|
||||
fe_cond_select :: #force_no_inline proc "contextless" (
|
||||
out1, arg1, arg2: $T,
|
||||
arg3: int,
|
||||
) where T == ^Tight_Field_Element || T == ^Loose_Field_Element {
|
||||
mask := (u64(arg3) * 0xffffffffffffffff)
|
||||
x1 := ((mask & arg2[0]) | ((~mask) & arg1[0]))
|
||||
x2 := ((mask & arg2[1]) | ((~mask) & arg1[1]))
|
||||
x3 := ((mask & arg2[2]) | ((~mask) & arg1[2]))
|
||||
x4 := ((mask & arg2[3]) | ((~mask) & arg1[3]))
|
||||
x5 := ((mask & arg2[4]) | ((~mask) & arg1[4]))
|
||||
out1[0] = x1
|
||||
out1[1] = x2
|
||||
out1[2] = x3
|
||||
out1[3] = x4
|
||||
out1[4] = x5
|
||||
}
|
||||
|
||||
fe_cond_negate :: proc "contextless" (out1, arg1: ^Tight_Field_Element, ctrl: int) {
|
||||
tmp1: Tight_Field_Element = ---
|
||||
fe_carry_opp(&tmp1, arg1)
|
||||
fe_cond_select(out1, arg1, &tmp1, ctrl)
|
||||
|
||||
fe_clear(&tmp1)
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ package field_curve25519
|
||||
//
|
||||
// While the base implementation is provably correct, this implementation
|
||||
// makes no such claims as the port and optimizations were done by hand.
|
||||
// At some point, it may be worth adding support to fiat-crypto for
|
||||
// generating Odin output.
|
||||
//
|
||||
// TODO:
|
||||
// * When fiat-crypto supports it, using a saturated 64-bit limbs
|
||||
@@ -44,7 +42,10 @@ import "core:math/bits"
|
||||
Loose_Field_Element :: distinct [5]u64
|
||||
Tight_Field_Element :: distinct [5]u64
|
||||
|
||||
SQRT_M1 := Tight_Field_Element{
|
||||
FE_ZERO := Tight_Field_Element{0, 0, 0, 0, 0}
|
||||
FE_ONE := Tight_Field_Element{1, 0, 0, 0, 0}
|
||||
|
||||
FE_SQRT_M1 := Tight_Field_Element {
|
||||
1718705420411056,
|
||||
234908883556509,
|
||||
2233514472574048,
|
||||
@@ -52,7 +53,13 @@ SQRT_M1 := Tight_Field_Element{
|
||||
765476049583133,
|
||||
}
|
||||
|
||||
_addcarryx_u51 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
|
||||
_addcarryx_u51 :: #force_inline proc "contextless" (
|
||||
arg1: fiat.u1,
|
||||
arg2, arg3: u64,
|
||||
) -> (
|
||||
out1: u64,
|
||||
out2: fiat.u1,
|
||||
) {
|
||||
x1 := ((u64(arg1) + arg2) + arg3)
|
||||
x2 := (x1 & 0x7ffffffffffff)
|
||||
x3 := fiat.u1((x1 >> 51))
|
||||
@@ -61,7 +68,13 @@ _addcarryx_u51 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u
|
||||
return
|
||||
}
|
||||
|
||||
_subborrowx_u51 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
|
||||
_subborrowx_u51 :: #force_inline proc "contextless" (
|
||||
arg1: fiat.u1,
|
||||
arg2, arg3: u64,
|
||||
) -> (
|
||||
out1: u64,
|
||||
out2: fiat.u1,
|
||||
) {
|
||||
x1 := ((i64(arg2) - i64(arg1)) - i64(arg3))
|
||||
x2 := fiat.i1((x1 >> 51))
|
||||
x3 := (u64(x1) & 0x7ffffffffffff)
|
||||
@@ -70,7 +83,7 @@ _subborrowx_u51 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3:
|
||||
return
|
||||
}
|
||||
|
||||
fe_carry_mul :: proc (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Element) {
|
||||
fe_carry_mul :: proc "contextless" (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Element) {
|
||||
x2, x1 := bits.mul_u64(arg1[4], (arg2[4] * 0x13))
|
||||
x4, x3 := bits.mul_u64(arg1[4], (arg2[3] * 0x13))
|
||||
x6, x5 := bits.mul_u64(arg1[4], (arg2[2] * 0x13))
|
||||
@@ -169,7 +182,7 @@ fe_carry_mul :: proc (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Eleme
|
||||
out1[4] = x152
|
||||
}
|
||||
|
||||
fe_carry_square :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
|
||||
fe_carry_square :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
|
||||
x1 := (arg1[4] * 0x13)
|
||||
x2 := (x1 * 0x2)
|
||||
x3 := (arg1[4] * 0x2)
|
||||
@@ -305,8 +318,11 @@ fe_opp :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_Ele
|
||||
out1[4] = x5
|
||||
}
|
||||
|
||||
@(optimization_mode="none")
|
||||
fe_cond_assign :: #force_no_inline proc "contextless" (out1, arg1: ^Tight_Field_Element, arg2: int) {
|
||||
@(optimization_mode = "none")
|
||||
fe_cond_assign :: #force_no_inline proc "contextless" (
|
||||
out1, arg1: ^Tight_Field_Element,
|
||||
arg2: int,
|
||||
) {
|
||||
x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0])
|
||||
x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1])
|
||||
x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2])
|
||||
@@ -527,7 +543,10 @@ fe_relax :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_E
|
||||
out1[4] = x5
|
||||
}
|
||||
|
||||
fe_carry_scmul_121666 :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
|
||||
fe_carry_scmul_121666 :: proc "contextless" (
|
||||
out1: ^Tight_Field_Element,
|
||||
arg1: ^Loose_Field_Element,
|
||||
) {
|
||||
x2, x1 := bits.mul_u64(0x1db42, arg1[4])
|
||||
x4, x3 := bits.mul_u64(0x1db42, arg1[3])
|
||||
x6, x5 := bits.mul_u64(0x1db42, arg1[2])
|
||||
@@ -565,54 +584,3 @@ fe_carry_scmul_121666 :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_El
|
||||
out1[3] = x27
|
||||
out1[4] = x32
|
||||
}
|
||||
|
||||
// The following routines were added by hand, and do not come from fiat-crypto.
|
||||
|
||||
fe_zero :: proc "contextless" (out1: ^Tight_Field_Element) {
|
||||
out1[0] = 0
|
||||
out1[1] = 0
|
||||
out1[2] = 0
|
||||
out1[3] = 0
|
||||
out1[4] = 0
|
||||
}
|
||||
|
||||
fe_one :: proc "contextless" (out1: ^Tight_Field_Element) {
|
||||
out1[0] = 1
|
||||
out1[1] = 0
|
||||
out1[2] = 0
|
||||
out1[3] = 0
|
||||
out1[4] = 0
|
||||
}
|
||||
|
||||
fe_set :: proc "contextless" (out1, arg1: ^Tight_Field_Element) {
|
||||
x1 := arg1[0]
|
||||
x2 := arg1[1]
|
||||
x3 := arg1[2]
|
||||
x4 := arg1[3]
|
||||
x5 := arg1[4]
|
||||
out1[0] = x1
|
||||
out1[1] = x2
|
||||
out1[2] = x3
|
||||
out1[3] = x4
|
||||
out1[4] = x5
|
||||
}
|
||||
|
||||
@(optimization_mode="none")
|
||||
fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: int) {
|
||||
mask := -u64(arg1)
|
||||
x := (out1[0] ~ out2[0]) & mask
|
||||
x1, y1 := out1[0] ~ x, out2[0] ~ x
|
||||
x = (out1[1] ~ out2[1]) & mask
|
||||
x2, y2 := out1[1] ~ x, out2[1] ~ x
|
||||
x = (out1[2] ~ out2[2]) & mask
|
||||
x3, y3 := out1[2] ~ x, out2[2] ~ x
|
||||
x = (out1[3] ~ out2[3]) & mask
|
||||
x4, y4 := out1[3] ~ x, out2[3] ~ x
|
||||
x = (out1[4] ~ out2[4]) & mask
|
||||
x5, y5 := out1[4] ~ x, out2[4] ~ x
|
||||
out1[0], out2[0] = x1, y1
|
||||
out1[1], out2[1] = x2, y2
|
||||
out1[2], out2[2] = x3, y3
|
||||
out1[3], out2[3] = x4, y4
|
||||
out1[4], out2[4] = x5, y5
|
||||
}
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
package field_poly1305
|
||||
|
||||
import "base:intrinsics"
|
||||
import "core:encoding/endian"
|
||||
import "core:mem"
|
||||
|
||||
fe_relax_cast :: #force_inline proc "contextless" (arg1: ^Tight_Field_Element) -> ^Loose_Field_Element {
|
||||
fe_relax_cast :: #force_inline proc "contextless" (
|
||||
arg1: ^Tight_Field_Element,
|
||||
) -> ^Loose_Field_Element {
|
||||
return transmute(^Loose_Field_Element)(arg1)
|
||||
}
|
||||
|
||||
fe_tighten_cast :: #force_inline proc "contextless" (arg1: ^Loose_Field_Element) -> ^Tight_Field_Element {
|
||||
fe_tighten_cast :: #force_inline proc "contextless" (
|
||||
arg1: ^Loose_Field_Element,
|
||||
) -> ^Tight_Field_Element {
|
||||
return transmute(^Tight_Field_Element)(arg1)
|
||||
}
|
||||
|
||||
fe_from_bytes :: #force_inline proc (out1: ^Tight_Field_Element, arg1: []byte, arg2: byte) {
|
||||
fe_from_bytes :: #force_inline proc "contextless" (
|
||||
out1: ^Tight_Field_Element,
|
||||
arg1: []byte,
|
||||
arg2: byte,
|
||||
) {
|
||||
// fiat-crypto's deserialization routine effectively processes a
|
||||
// single byte at a time, and wants 256-bits of input for a value
|
||||
// that will be 128-bits or 129-bits.
|
||||
@@ -20,7 +29,9 @@ fe_from_bytes :: #force_inline proc (out1: ^Tight_Field_Element, arg1: []byte, a
|
||||
// makes implementing the actual MAC block processing considerably
|
||||
// neater.
|
||||
|
||||
assert(len(arg1) == 16)
|
||||
if len(arg1) != 16 {
|
||||
intrinsics.trap()
|
||||
}
|
||||
|
||||
// While it may be unwise to do deserialization here on our
|
||||
// own when fiat-crypto provides equivalent functionality,
|
||||
@@ -51,3 +62,35 @@ fe_from_u64s :: proc "contextless" (out1: ^Tight_Field_Element, lo, hi: u64) {
|
||||
// This routine is only used to deserialize `r` which is confidential.
|
||||
mem.zero_explicit(&tmp, size_of(tmp))
|
||||
}
|
||||
|
||||
fe_zero :: proc "contextless" (out1: ^Tight_Field_Element) {
|
||||
out1[0] = 0
|
||||
out1[1] = 0
|
||||
out1[2] = 0
|
||||
}
|
||||
|
||||
fe_set :: #force_inline proc "contextless" (out1, arg1: ^Tight_Field_Element) {
|
||||
x1 := arg1[0]
|
||||
x2 := arg1[1]
|
||||
x3 := arg1[2]
|
||||
out1[0] = x1
|
||||
out1[1] = x2
|
||||
out1[2] = x3
|
||||
}
|
||||
|
||||
@(optimization_mode = "none")
|
||||
fe_cond_swap :: #force_no_inline proc "contextless" (
|
||||
out1, out2: ^Tight_Field_Element,
|
||||
arg1: bool,
|
||||
) {
|
||||
mask := (u64(arg1) * 0xffffffffffffffff)
|
||||
x := (out1[0] ~ out2[0]) & mask
|
||||
x1, y1 := out1[0] ~ x, out2[0] ~ x
|
||||
x = (out1[1] ~ out2[1]) & mask
|
||||
x2, y2 := out1[1] ~ x, out2[1] ~ x
|
||||
x = (out1[2] ~ out2[2]) & mask
|
||||
x3, y3 := out1[2] ~ x, out2[2] ~ x
|
||||
out1[0], out2[0] = x1, y1
|
||||
out1[1], out2[1] = x2, y2
|
||||
out1[2], out2[2] = x3, y3
|
||||
}
|
||||
|
||||
@@ -39,7 +39,13 @@ import "core:math/bits"
|
||||
Loose_Field_Element :: distinct [3]u64
|
||||
Tight_Field_Element :: distinct [3]u64
|
||||
|
||||
_addcarryx_u44 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
|
||||
_addcarryx_u44 :: #force_inline proc "contextless" (
|
||||
arg1: fiat.u1,
|
||||
arg2, arg3: u64,
|
||||
) -> (
|
||||
out1: u64,
|
||||
out2: fiat.u1,
|
||||
) {
|
||||
x1 := ((u64(arg1) + arg2) + arg3)
|
||||
x2 := (x1 & 0xfffffffffff)
|
||||
x3 := fiat.u1((x1 >> 44))
|
||||
@@ -48,7 +54,13 @@ _addcarryx_u44 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u
|
||||
return
|
||||
}
|
||||
|
||||
_subborrowx_u44 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
|
||||
_subborrowx_u44 :: #force_inline proc "contextless" (
|
||||
arg1: fiat.u1,
|
||||
arg2, arg3: u64,
|
||||
) -> (
|
||||
out1: u64,
|
||||
out2: fiat.u1,
|
||||
) {
|
||||
x1 := ((i64(arg2) - i64(arg1)) - i64(arg3))
|
||||
x2 := fiat.i1((x1 >> 44))
|
||||
x3 := (u64(x1) & 0xfffffffffff)
|
||||
@@ -57,7 +69,13 @@ _subborrowx_u44 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3:
|
||||
return
|
||||
}
|
||||
|
||||
_addcarryx_u43 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
|
||||
_addcarryx_u43 :: #force_inline proc "contextless" (
|
||||
arg1: fiat.u1,
|
||||
arg2, arg3: u64,
|
||||
) -> (
|
||||
out1: u64,
|
||||
out2: fiat.u1,
|
||||
) {
|
||||
x1 := ((u64(arg1) + arg2) + arg3)
|
||||
x2 := (x1 & 0x7ffffffffff)
|
||||
x3 := fiat.u1((x1 >> 43))
|
||||
@@ -66,7 +84,13 @@ _addcarryx_u43 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u
|
||||
return
|
||||
}
|
||||
|
||||
_subborrowx_u43 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3: u64) -> (out1: u64, out2: fiat.u1) {
|
||||
_subborrowx_u43 :: #force_inline proc "contextless" (
|
||||
arg1: fiat.u1,
|
||||
arg2, arg3: u64,
|
||||
) -> (
|
||||
out1: u64,
|
||||
out2: fiat.u1,
|
||||
) {
|
||||
x1 := ((i64(arg2) - i64(arg1)) - i64(arg3))
|
||||
x2 := fiat.i1((x1 >> 43))
|
||||
x3 := (u64(x1) & 0x7ffffffffff)
|
||||
@@ -75,7 +99,7 @@ _subborrowx_u43 :: #force_inline proc "contextless" (arg1: fiat.u1, arg2, arg3:
|
||||
return
|
||||
}
|
||||
|
||||
fe_carry_mul :: proc (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Element) {
|
||||
fe_carry_mul :: proc "contextless" (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Element) {
|
||||
x2, x1 := bits.mul_u64(arg1[2], (arg2[2] * 0x5))
|
||||
x4, x3 := bits.mul_u64(arg1[2], (arg2[1] * 0xa))
|
||||
x6, x5 := bits.mul_u64(arg1[1], (arg2[2] * 0xa))
|
||||
@@ -120,7 +144,7 @@ fe_carry_mul :: proc (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Eleme
|
||||
out1[2] = x62
|
||||
}
|
||||
|
||||
fe_carry_square :: proc (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
|
||||
fe_carry_square :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) {
|
||||
x1 := (arg1[2] * 0x5)
|
||||
x2 := (x1 * 0x2)
|
||||
x3 := (arg1[2] * 0x2)
|
||||
@@ -201,8 +225,11 @@ fe_opp :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_Ele
|
||||
out1[2] = x3
|
||||
}
|
||||
|
||||
@(optimization_mode="none")
|
||||
fe_cond_assign :: #force_no_inline proc "contextless" (out1, arg1: ^Tight_Field_Element, arg2: bool) {
|
||||
@(optimization_mode = "none")
|
||||
fe_cond_assign :: #force_no_inline proc "contextless" (
|
||||
out1, arg1: ^Tight_Field_Element,
|
||||
arg2: bool,
|
||||
) {
|
||||
x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0])
|
||||
x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1])
|
||||
x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2])
|
||||
@@ -325,34 +352,3 @@ fe_relax :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_E
|
||||
out1[1] = x2
|
||||
out1[2] = x3
|
||||
}
|
||||
|
||||
// The following routines were added by hand, and do not come from fiat-crypto.
|
||||
|
||||
fe_zero :: proc "contextless" (out1: ^Tight_Field_Element) {
|
||||
out1[0] = 0
|
||||
out1[1] = 0
|
||||
out1[2] = 0
|
||||
}
|
||||
|
||||
fe_set :: #force_inline proc "contextless" (out1, arg1: ^Tight_Field_Element) {
|
||||
x1 := arg1[0]
|
||||
x2 := arg1[1]
|
||||
x3 := arg1[2]
|
||||
out1[0] = x1
|
||||
out1[1] = x2
|
||||
out1[2] = x3
|
||||
}
|
||||
|
||||
@(optimization_mode="none")
|
||||
fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: bool) {
|
||||
mask := -u64(arg1)
|
||||
x := (out1[0] ~ out2[0]) & mask
|
||||
x1, y1 := out1[0] ~ x, out2[0] ~ x
|
||||
x = (out1[1] ~ out2[1]) & mask
|
||||
x2, y2 := out1[1] ~ x, out2[1] ~ x
|
||||
x = (out1[2] ~ out2[2]) & mask
|
||||
x3, y3 := out1[2] ~ x, out2[2] ~ x
|
||||
out1[0], out2[0] = x1, y1
|
||||
out1[1], out2[1] = x2, y2
|
||||
out1[2], out2[2] = x3, y3
|
||||
}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
package field_scalar25519
|
||||
|
||||
import "base:intrinsics"
|
||||
import "core:encoding/endian"
|
||||
import "core:math/bits"
|
||||
import "core:mem"
|
||||
|
||||
@(private)
|
||||
_TWO_168 := Montgomery_Domain_Field_Element {
|
||||
0x5b8ab432eac74798,
|
||||
0x38afddd6de59d5d7,
|
||||
0xa2c131b399411b7c,
|
||||
0x6329a7ed9ce5a30,
|
||||
}
|
||||
@(private)
|
||||
_TWO_336 := Montgomery_Domain_Field_Element {
|
||||
0xbd3d108e2b35ecc5,
|
||||
0x5c3a3718bdf9c90b,
|
||||
0x63aa97a331b4f2ee,
|
||||
0x3d217f5be65cb5c,
|
||||
}
|
||||
|
||||
fe_clear :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) {
|
||||
mem.zero_explicit(arg1, size_of(Montgomery_Domain_Field_Element))
|
||||
}
|
||||
|
||||
fe_from_bytes :: proc "contextless" (
|
||||
out1: ^Montgomery_Domain_Field_Element,
|
||||
arg1: ^[32]byte,
|
||||
unsafe_assume_canonical := false,
|
||||
) -> bool {
|
||||
tmp := Non_Montgomery_Domain_Field_Element {
|
||||
endian.unchecked_get_u64le(arg1[0:]),
|
||||
endian.unchecked_get_u64le(arg1[8:]),
|
||||
endian.unchecked_get_u64le(arg1[16:]),
|
||||
endian.unchecked_get_u64le(arg1[24:]),
|
||||
}
|
||||
defer mem.zero_explicit(&tmp, size_of(tmp))
|
||||
|
||||
// Check that tmp is in the the range [0, ELL).
|
||||
if !unsafe_assume_canonical {
|
||||
_, borrow := bits.sub_u64(ELL[0] - 1, tmp[0], 0)
|
||||
_, borrow = bits.sub_u64(ELL[1], tmp[1], borrow)
|
||||
_, borrow = bits.sub_u64(ELL[2], tmp[2], borrow)
|
||||
_, borrow = bits.sub_u64(ELL[3], tmp[3], borrow)
|
||||
if borrow != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fe_to_montgomery(out1, &tmp)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fe_from_bytes_rfc8032 :: proc "contextless" (
|
||||
out1: ^Montgomery_Domain_Field_Element,
|
||||
arg1: ^[32]byte,
|
||||
) {
|
||||
tmp: [64]byte
|
||||
copy(tmp[:], arg1[:])
|
||||
|
||||
// Apply "clamping" as in RFC 8032.
|
||||
tmp[0] &= 248
|
||||
tmp[31] &= 127
|
||||
tmp[31] |= 64 // Sets the 254th bit, so the encoding is non-canonical.
|
||||
|
||||
fe_from_bytes_wide(out1, &tmp)
|
||||
|
||||
mem.zero_explicit(&tmp, size_of(tmp))
|
||||
}
|
||||
|
||||
fe_from_bytes_wide :: proc "contextless" (
|
||||
out1: ^Montgomery_Domain_Field_Element,
|
||||
arg1: ^[64]byte,
|
||||
) {
|
||||
tmp: Montgomery_Domain_Field_Element
|
||||
// Use Frank Denis' trick, as documented by Filippo Valsorda
|
||||
// at https://words.filippo.io/dispatches/wide-reduction/
|
||||
//
|
||||
// x = c * 2^336 + b * 2^168 + a mod l
|
||||
_fe_from_bytes_short(out1, arg1[:21]) // a
|
||||
|
||||
_fe_from_bytes_short(&tmp, arg1[21:42]) // b
|
||||
fe_mul(&tmp, &tmp, &_TWO_168) // b * 2^168
|
||||
fe_add(out1, out1, &tmp) // a + b * 2^168
|
||||
|
||||
_fe_from_bytes_short(&tmp, arg1[42:]) // c
|
||||
fe_mul(&tmp, &tmp, &_TWO_336) // c * 2^336
|
||||
fe_add(out1, out1, &tmp) // a + b * 2^168 + c * 2^336
|
||||
|
||||
fe_clear(&tmp)
|
||||
}
|
||||
|
||||
@(private)
|
||||
_fe_from_bytes_short :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element, arg1: []byte) {
|
||||
// INVARIANT: len(arg1) < 32.
|
||||
if len(arg1) >= 32 {
|
||||
intrinsics.trap()
|
||||
}
|
||||
tmp: [32]byte
|
||||
copy(tmp[:], arg1)
|
||||
|
||||
_ = fe_from_bytes(out1, &tmp, true)
|
||||
mem.zero_explicit(&tmp, size_of(tmp))
|
||||
}
|
||||
|
||||
fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) {
|
||||
if len(out1) != 32 {
|
||||
intrinsics.trap()
|
||||
}
|
||||
|
||||
tmp: Non_Montgomery_Domain_Field_Element
|
||||
fe_from_montgomery(&tmp, arg1)
|
||||
|
||||
endian.unchecked_put_u64le(out1[0:], tmp[0])
|
||||
endian.unchecked_put_u64le(out1[8:], tmp[1])
|
||||
endian.unchecked_put_u64le(out1[16:], tmp[2])
|
||||
endian.unchecked_put_u64le(out1[24:], tmp[3])
|
||||
|
||||
mem.zero_explicit(&tmp, size_of(tmp))
|
||||
}
|
||||
|
||||
fe_equal :: proc "contextless" (arg1, arg2: ^Montgomery_Domain_Field_Element) -> int {
|
||||
tmp: Montgomery_Domain_Field_Element
|
||||
fe_sub(&tmp, arg1, arg2)
|
||||
|
||||
// This will only underflow iff arg1 == arg2, and we return the borrow,
|
||||
// which will be 1.
|
||||
_, borrow := bits.sub_u64(fe_non_zero(&tmp), 1, 0)
|
||||
|
||||
fe_clear(&tmp)
|
||||
|
||||
return int(borrow)
|
||||
}
|
||||
|
||||
fe_zero :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) {
|
||||
out1[0] = 0
|
||||
out1[1] = 0
|
||||
out1[2] = 0
|
||||
out1[3] = 0
|
||||
}
|
||||
|
||||
fe_set :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) {
|
||||
x1 := arg1[0]
|
||||
x2 := arg1[1]
|
||||
x3 := arg1[2]
|
||||
x4 := arg1[3]
|
||||
out1[0] = x1
|
||||
out1[1] = x2
|
||||
out1[2] = x3
|
||||
out1[3] = x4
|
||||
}
|
||||
@@ -0,0 +1,535 @@
|
||||
// The BSD 1-Clause License (BSD-1-Clause)
|
||||
//
|
||||
// Copyright (c) 2015-2020 the fiat-crypto authors (see the AUTHORS file)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design,
|
||||
// Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package field_scalar25519
|
||||
|
||||
// The file provides arithmetic on the field Z/(2^252+27742317777372353535851937790883648493)
|
||||
// using a 64-bit Montgomery form internal representation. It is derived
|
||||
// primarily from the machine generated Golang output from the fiat-crypto
|
||||
// project.
|
||||
//
|
||||
// While the base implementation is provably correct, this implementation
|
||||
// makes no such claims as the port and optimizations were done by hand.
|
||||
|
||||
import fiat "core:crypto/_fiat"
|
||||
import "core:math/bits"
|
||||
|
||||
// ELL is the saturated representation of the field order, least-significant
|
||||
// limb first.
|
||||
ELL :: [4]u64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000}
|
||||
|
||||
Montgomery_Domain_Field_Element :: distinct [4]u64
|
||||
Non_Montgomery_Domain_Field_Element :: distinct [4]u64
|
||||
|
||||
fe_mul :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) {
|
||||
x1 := arg1[1]
|
||||
x2 := arg1[2]
|
||||
x3 := arg1[3]
|
||||
x4 := arg1[0]
|
||||
x6, x5 := bits.mul_u64(x4, arg2[3])
|
||||
x8, x7 := bits.mul_u64(x4, arg2[2])
|
||||
x10, x9 := bits.mul_u64(x4, arg2[1])
|
||||
x12, x11 := bits.mul_u64(x4, arg2[0])
|
||||
x13, x14 := bits.add_u64(x12, x9, u64(0x0))
|
||||
x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14)))
|
||||
x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16)))
|
||||
x19 := (u64(fiat.u1(x18)) + x6)
|
||||
_, x20 := bits.mul_u64(x11, 0xd2b51da312547e1b)
|
||||
x23, x22 := bits.mul_u64(x20, 0x1000000000000000)
|
||||
x25, x24 := bits.mul_u64(x20, 0x14def9dea2f79cd6)
|
||||
x27, x26 := bits.mul_u64(x20, 0x5812631a5cf5d3ed)
|
||||
x28, x29 := bits.add_u64(x27, x24, u64(0x0))
|
||||
x30 := (u64(fiat.u1(x29)) + x25)
|
||||
_, x32 := bits.add_u64(x11, x26, u64(0x0))
|
||||
x33, x34 := bits.add_u64(x13, x28, u64(fiat.u1(x32)))
|
||||
x35, x36 := bits.add_u64(x15, x30, u64(fiat.u1(x34)))
|
||||
x37, x38 := bits.add_u64(x17, x22, u64(fiat.u1(x36)))
|
||||
x39, x40 := bits.add_u64(x19, x23, u64(fiat.u1(x38)))
|
||||
x42, x41 := bits.mul_u64(x1, arg2[3])
|
||||
x44, x43 := bits.mul_u64(x1, arg2[2])
|
||||
x46, x45 := bits.mul_u64(x1, arg2[1])
|
||||
x48, x47 := bits.mul_u64(x1, arg2[0])
|
||||
x49, x50 := bits.add_u64(x48, x45, u64(0x0))
|
||||
x51, x52 := bits.add_u64(x46, x43, u64(fiat.u1(x50)))
|
||||
x53, x54 := bits.add_u64(x44, x41, u64(fiat.u1(x52)))
|
||||
x55 := (u64(fiat.u1(x54)) + x42)
|
||||
x56, x57 := bits.add_u64(x33, x47, u64(0x0))
|
||||
x58, x59 := bits.add_u64(x35, x49, u64(fiat.u1(x57)))
|
||||
x60, x61 := bits.add_u64(x37, x51, u64(fiat.u1(x59)))
|
||||
x62, x63 := bits.add_u64(x39, x53, u64(fiat.u1(x61)))
|
||||
x64, x65 := bits.add_u64(u64(fiat.u1(x40)), x55, u64(fiat.u1(x63)))
|
||||
_, x66 := bits.mul_u64(x56, 0xd2b51da312547e1b)
|
||||
x69, x68 := bits.mul_u64(x66, 0x1000000000000000)
|
||||
x71, x70 := bits.mul_u64(x66, 0x14def9dea2f79cd6)
|
||||
x73, x72 := bits.mul_u64(x66, 0x5812631a5cf5d3ed)
|
||||
x74, x75 := bits.add_u64(x73, x70, u64(0x0))
|
||||
x76 := (u64(fiat.u1(x75)) + x71)
|
||||
_, x78 := bits.add_u64(x56, x72, u64(0x0))
|
||||
x79, x80 := bits.add_u64(x58, x74, u64(fiat.u1(x78)))
|
||||
x81, x82 := bits.add_u64(x60, x76, u64(fiat.u1(x80)))
|
||||
x83, x84 := bits.add_u64(x62, x68, u64(fiat.u1(x82)))
|
||||
x85, x86 := bits.add_u64(x64, x69, u64(fiat.u1(x84)))
|
||||
x87 := (u64(fiat.u1(x86)) + u64(fiat.u1(x65)))
|
||||
x89, x88 := bits.mul_u64(x2, arg2[3])
|
||||
x91, x90 := bits.mul_u64(x2, arg2[2])
|
||||
x93, x92 := bits.mul_u64(x2, arg2[1])
|
||||
x95, x94 := bits.mul_u64(x2, arg2[0])
|
||||
x96, x97 := bits.add_u64(x95, x92, u64(0x0))
|
||||
x98, x99 := bits.add_u64(x93, x90, u64(fiat.u1(x97)))
|
||||
x100, x101 := bits.add_u64(x91, x88, u64(fiat.u1(x99)))
|
||||
x102 := (u64(fiat.u1(x101)) + x89)
|
||||
x103, x104 := bits.add_u64(x79, x94, u64(0x0))
|
||||
x105, x106 := bits.add_u64(x81, x96, u64(fiat.u1(x104)))
|
||||
x107, x108 := bits.add_u64(x83, x98, u64(fiat.u1(x106)))
|
||||
x109, x110 := bits.add_u64(x85, x100, u64(fiat.u1(x108)))
|
||||
x111, x112 := bits.add_u64(x87, x102, u64(fiat.u1(x110)))
|
||||
_, x113 := bits.mul_u64(x103, 0xd2b51da312547e1b)
|
||||
x116, x115 := bits.mul_u64(x113, 0x1000000000000000)
|
||||
x118, x117 := bits.mul_u64(x113, 0x14def9dea2f79cd6)
|
||||
x120, x119 := bits.mul_u64(x113, 0x5812631a5cf5d3ed)
|
||||
x121, x122 := bits.add_u64(x120, x117, u64(0x0))
|
||||
x123 := (u64(fiat.u1(x122)) + x118)
|
||||
_, x125 := bits.add_u64(x103, x119, u64(0x0))
|
||||
x126, x127 := bits.add_u64(x105, x121, u64(fiat.u1(x125)))
|
||||
x128, x129 := bits.add_u64(x107, x123, u64(fiat.u1(x127)))
|
||||
x130, x131 := bits.add_u64(x109, x115, u64(fiat.u1(x129)))
|
||||
x132, x133 := bits.add_u64(x111, x116, u64(fiat.u1(x131)))
|
||||
x134 := (u64(fiat.u1(x133)) + u64(fiat.u1(x112)))
|
||||
x136, x135 := bits.mul_u64(x3, arg2[3])
|
||||
x138, x137 := bits.mul_u64(x3, arg2[2])
|
||||
x140, x139 := bits.mul_u64(x3, arg2[1])
|
||||
x142, x141 := bits.mul_u64(x3, arg2[0])
|
||||
x143, x144 := bits.add_u64(x142, x139, u64(0x0))
|
||||
x145, x146 := bits.add_u64(x140, x137, u64(fiat.u1(x144)))
|
||||
x147, x148 := bits.add_u64(x138, x135, u64(fiat.u1(x146)))
|
||||
x149 := (u64(fiat.u1(x148)) + x136)
|
||||
x150, x151 := bits.add_u64(x126, x141, u64(0x0))
|
||||
x152, x153 := bits.add_u64(x128, x143, u64(fiat.u1(x151)))
|
||||
x154, x155 := bits.add_u64(x130, x145, u64(fiat.u1(x153)))
|
||||
x156, x157 := bits.add_u64(x132, x147, u64(fiat.u1(x155)))
|
||||
x158, x159 := bits.add_u64(x134, x149, u64(fiat.u1(x157)))
|
||||
_, x160 := bits.mul_u64(x150, 0xd2b51da312547e1b)
|
||||
x163, x162 := bits.mul_u64(x160, 0x1000000000000000)
|
||||
x165, x164 := bits.mul_u64(x160, 0x14def9dea2f79cd6)
|
||||
x167, x166 := bits.mul_u64(x160, 0x5812631a5cf5d3ed)
|
||||
x168, x169 := bits.add_u64(x167, x164, u64(0x0))
|
||||
x170 := (u64(fiat.u1(x169)) + x165)
|
||||
_, x172 := bits.add_u64(x150, x166, u64(0x0))
|
||||
x173, x174 := bits.add_u64(x152, x168, u64(fiat.u1(x172)))
|
||||
x175, x176 := bits.add_u64(x154, x170, u64(fiat.u1(x174)))
|
||||
x177, x178 := bits.add_u64(x156, x162, u64(fiat.u1(x176)))
|
||||
x179, x180 := bits.add_u64(x158, x163, u64(fiat.u1(x178)))
|
||||
x181 := (u64(fiat.u1(x180)) + u64(fiat.u1(x159)))
|
||||
x182, x183 := bits.sub_u64(x173, 0x5812631a5cf5d3ed, u64(0x0))
|
||||
x184, x185 := bits.sub_u64(x175, 0x14def9dea2f79cd6, u64(fiat.u1(x183)))
|
||||
x186, x187 := bits.sub_u64(x177, u64(0x0), u64(fiat.u1(x185)))
|
||||
x188, x189 := bits.sub_u64(x179, 0x1000000000000000, u64(fiat.u1(x187)))
|
||||
_, x191 := bits.sub_u64(x181, u64(0x0), u64(fiat.u1(x189)))
|
||||
x192 := fiat.cmovznz_u64(fiat.u1(x191), x182, x173)
|
||||
x193 := fiat.cmovznz_u64(fiat.u1(x191), x184, x175)
|
||||
x194 := fiat.cmovznz_u64(fiat.u1(x191), x186, x177)
|
||||
x195 := fiat.cmovznz_u64(fiat.u1(x191), x188, x179)
|
||||
out1[0] = x192
|
||||
out1[1] = x193
|
||||
out1[2] = x194
|
||||
out1[3] = x195
|
||||
}
|
||||
|
||||
fe_square :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) {
|
||||
x1 := arg1[1]
|
||||
x2 := arg1[2]
|
||||
x3 := arg1[3]
|
||||
x4 := arg1[0]
|
||||
x6, x5 := bits.mul_u64(x4, arg1[3])
|
||||
x8, x7 := bits.mul_u64(x4, arg1[2])
|
||||
x10, x9 := bits.mul_u64(x4, arg1[1])
|
||||
x12, x11 := bits.mul_u64(x4, arg1[0])
|
||||
x13, x14 := bits.add_u64(x12, x9, u64(0x0))
|
||||
x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14)))
|
||||
x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16)))
|
||||
x19 := (u64(fiat.u1(x18)) + x6)
|
||||
_, x20 := bits.mul_u64(x11, 0xd2b51da312547e1b)
|
||||
x23, x22 := bits.mul_u64(x20, 0x1000000000000000)
|
||||
x25, x24 := bits.mul_u64(x20, 0x14def9dea2f79cd6)
|
||||
x27, x26 := bits.mul_u64(x20, 0x5812631a5cf5d3ed)
|
||||
x28, x29 := bits.add_u64(x27, x24, u64(0x0))
|
||||
x30 := (u64(fiat.u1(x29)) + x25)
|
||||
_, x32 := bits.add_u64(x11, x26, u64(0x0))
|
||||
x33, x34 := bits.add_u64(x13, x28, u64(fiat.u1(x32)))
|
||||
x35, x36 := bits.add_u64(x15, x30, u64(fiat.u1(x34)))
|
||||
x37, x38 := bits.add_u64(x17, x22, u64(fiat.u1(x36)))
|
||||
x39, x40 := bits.add_u64(x19, x23, u64(fiat.u1(x38)))
|
||||
x42, x41 := bits.mul_u64(x1, arg1[3])
|
||||
x44, x43 := bits.mul_u64(x1, arg1[2])
|
||||
x46, x45 := bits.mul_u64(x1, arg1[1])
|
||||
x48, x47 := bits.mul_u64(x1, arg1[0])
|
||||
x49, x50 := bits.add_u64(x48, x45, u64(0x0))
|
||||
x51, x52 := bits.add_u64(x46, x43, u64(fiat.u1(x50)))
|
||||
x53, x54 := bits.add_u64(x44, x41, u64(fiat.u1(x52)))
|
||||
x55 := (u64(fiat.u1(x54)) + x42)
|
||||
x56, x57 := bits.add_u64(x33, x47, u64(0x0))
|
||||
x58, x59 := bits.add_u64(x35, x49, u64(fiat.u1(x57)))
|
||||
x60, x61 := bits.add_u64(x37, x51, u64(fiat.u1(x59)))
|
||||
x62, x63 := bits.add_u64(x39, x53, u64(fiat.u1(x61)))
|
||||
x64, x65 := bits.add_u64(u64(fiat.u1(x40)), x55, u64(fiat.u1(x63)))
|
||||
_, x66 := bits.mul_u64(x56, 0xd2b51da312547e1b)
|
||||
x69, x68 := bits.mul_u64(x66, 0x1000000000000000)
|
||||
x71, x70 := bits.mul_u64(x66, 0x14def9dea2f79cd6)
|
||||
x73, x72 := bits.mul_u64(x66, 0x5812631a5cf5d3ed)
|
||||
x74, x75 := bits.add_u64(x73, x70, u64(0x0))
|
||||
x76 := (u64(fiat.u1(x75)) + x71)
|
||||
_, x78 := bits.add_u64(x56, x72, u64(0x0))
|
||||
x79, x80 := bits.add_u64(x58, x74, u64(fiat.u1(x78)))
|
||||
x81, x82 := bits.add_u64(x60, x76, u64(fiat.u1(x80)))
|
||||
x83, x84 := bits.add_u64(x62, x68, u64(fiat.u1(x82)))
|
||||
x85, x86 := bits.add_u64(x64, x69, u64(fiat.u1(x84)))
|
||||
x87 := (u64(fiat.u1(x86)) + u64(fiat.u1(x65)))
|
||||
x89, x88 := bits.mul_u64(x2, arg1[3])
|
||||
x91, x90 := bits.mul_u64(x2, arg1[2])
|
||||
x93, x92 := bits.mul_u64(x2, arg1[1])
|
||||
x95, x94 := bits.mul_u64(x2, arg1[0])
|
||||
x96, x97 := bits.add_u64(x95, x92, u64(0x0))
|
||||
x98, x99 := bits.add_u64(x93, x90, u64(fiat.u1(x97)))
|
||||
x100, x101 := bits.add_u64(x91, x88, u64(fiat.u1(x99)))
|
||||
x102 := (u64(fiat.u1(x101)) + x89)
|
||||
x103, x104 := bits.add_u64(x79, x94, u64(0x0))
|
||||
x105, x106 := bits.add_u64(x81, x96, u64(fiat.u1(x104)))
|
||||
x107, x108 := bits.add_u64(x83, x98, u64(fiat.u1(x106)))
|
||||
x109, x110 := bits.add_u64(x85, x100, u64(fiat.u1(x108)))
|
||||
x111, x112 := bits.add_u64(x87, x102, u64(fiat.u1(x110)))
|
||||
_, x113 := bits.mul_u64(x103, 0xd2b51da312547e1b)
|
||||
x116, x115 := bits.mul_u64(x113, 0x1000000000000000)
|
||||
x118, x117 := bits.mul_u64(x113, 0x14def9dea2f79cd6)
|
||||
x120, x119 := bits.mul_u64(x113, 0x5812631a5cf5d3ed)
|
||||
x121, x122 := bits.add_u64(x120, x117, u64(0x0))
|
||||
x123 := (u64(fiat.u1(x122)) + x118)
|
||||
_, x125 := bits.add_u64(x103, x119, u64(0x0))
|
||||
x126, x127 := bits.add_u64(x105, x121, u64(fiat.u1(x125)))
|
||||
x128, x129 := bits.add_u64(x107, x123, u64(fiat.u1(x127)))
|
||||
x130, x131 := bits.add_u64(x109, x115, u64(fiat.u1(x129)))
|
||||
x132, x133 := bits.add_u64(x111, x116, u64(fiat.u1(x131)))
|
||||
x134 := (u64(fiat.u1(x133)) + u64(fiat.u1(x112)))
|
||||
x136, x135 := bits.mul_u64(x3, arg1[3])
|
||||
x138, x137 := bits.mul_u64(x3, arg1[2])
|
||||
x140, x139 := bits.mul_u64(x3, arg1[1])
|
||||
x142, x141 := bits.mul_u64(x3, arg1[0])
|
||||
x143, x144 := bits.add_u64(x142, x139, u64(0x0))
|
||||
x145, x146 := bits.add_u64(x140, x137, u64(fiat.u1(x144)))
|
||||
x147, x148 := bits.add_u64(x138, x135, u64(fiat.u1(x146)))
|
||||
x149 := (u64(fiat.u1(x148)) + x136)
|
||||
x150, x151 := bits.add_u64(x126, x141, u64(0x0))
|
||||
x152, x153 := bits.add_u64(x128, x143, u64(fiat.u1(x151)))
|
||||
x154, x155 := bits.add_u64(x130, x145, u64(fiat.u1(x153)))
|
||||
x156, x157 := bits.add_u64(x132, x147, u64(fiat.u1(x155)))
|
||||
x158, x159 := bits.add_u64(x134, x149, u64(fiat.u1(x157)))
|
||||
_, x160 := bits.mul_u64(x150, 0xd2b51da312547e1b)
|
||||
x163, x162 := bits.mul_u64(x160, 0x1000000000000000)
|
||||
x165, x164 := bits.mul_u64(x160, 0x14def9dea2f79cd6)
|
||||
x167, x166 := bits.mul_u64(x160, 0x5812631a5cf5d3ed)
|
||||
x168, x169 := bits.add_u64(x167, x164, u64(0x0))
|
||||
x170 := (u64(fiat.u1(x169)) + x165)
|
||||
_, x172 := bits.add_u64(x150, x166, u64(0x0))
|
||||
x173, x174 := bits.add_u64(x152, x168, u64(fiat.u1(x172)))
|
||||
x175, x176 := bits.add_u64(x154, x170, u64(fiat.u1(x174)))
|
||||
x177, x178 := bits.add_u64(x156, x162, u64(fiat.u1(x176)))
|
||||
x179, x180 := bits.add_u64(x158, x163, u64(fiat.u1(x178)))
|
||||
x181 := (u64(fiat.u1(x180)) + u64(fiat.u1(x159)))
|
||||
x182, x183 := bits.sub_u64(x173, 0x5812631a5cf5d3ed, u64(0x0))
|
||||
x184, x185 := bits.sub_u64(x175, 0x14def9dea2f79cd6, u64(fiat.u1(x183)))
|
||||
x186, x187 := bits.sub_u64(x177, u64(0x0), u64(fiat.u1(x185)))
|
||||
x188, x189 := bits.sub_u64(x179, 0x1000000000000000, u64(fiat.u1(x187)))
|
||||
_, x191 := bits.sub_u64(x181, u64(0x0), u64(fiat.u1(x189)))
|
||||
x192 := fiat.cmovznz_u64(fiat.u1(x191), x182, x173)
|
||||
x193 := fiat.cmovznz_u64(fiat.u1(x191), x184, x175)
|
||||
x194 := fiat.cmovznz_u64(fiat.u1(x191), x186, x177)
|
||||
x195 := fiat.cmovznz_u64(fiat.u1(x191), x188, x179)
|
||||
out1[0] = x192
|
||||
out1[1] = x193
|
||||
out1[2] = x194
|
||||
out1[3] = x195
|
||||
}
|
||||
|
||||
fe_add :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) {
|
||||
x1, x2 := bits.add_u64(arg1[0], arg2[0], u64(0x0))
|
||||
x3, x4 := bits.add_u64(arg1[1], arg2[1], u64(fiat.u1(x2)))
|
||||
x5, x6 := bits.add_u64(arg1[2], arg2[2], u64(fiat.u1(x4)))
|
||||
x7, x8 := bits.add_u64(arg1[3], arg2[3], u64(fiat.u1(x6)))
|
||||
x9, x10 := bits.sub_u64(x1, 0x5812631a5cf5d3ed, u64(0x0))
|
||||
x11, x12 := bits.sub_u64(x3, 0x14def9dea2f79cd6, u64(fiat.u1(x10)))
|
||||
x13, x14 := bits.sub_u64(x5, u64(0x0), u64(fiat.u1(x12)))
|
||||
x15, x16 := bits.sub_u64(x7, 0x1000000000000000, u64(fiat.u1(x14)))
|
||||
_, x18 := bits.sub_u64(u64(fiat.u1(x8)), u64(0x0), u64(fiat.u1(x16)))
|
||||
x19 := fiat.cmovznz_u64(fiat.u1(x18), x9, x1)
|
||||
x20 := fiat.cmovznz_u64(fiat.u1(x18), x11, x3)
|
||||
x21 := fiat.cmovznz_u64(fiat.u1(x18), x13, x5)
|
||||
x22 := fiat.cmovznz_u64(fiat.u1(x18), x15, x7)
|
||||
out1[0] = x19
|
||||
out1[1] = x20
|
||||
out1[2] = x21
|
||||
out1[3] = x22
|
||||
}
|
||||
|
||||
fe_sub :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) {
|
||||
x1, x2 := bits.sub_u64(arg1[0], arg2[0], u64(0x0))
|
||||
x3, x4 := bits.sub_u64(arg1[1], arg2[1], u64(fiat.u1(x2)))
|
||||
x5, x6 := bits.sub_u64(arg1[2], arg2[2], u64(fiat.u1(x4)))
|
||||
x7, x8 := bits.sub_u64(arg1[3], arg2[3], u64(fiat.u1(x6)))
|
||||
x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff)
|
||||
x10, x11 := bits.add_u64(x1, (x9 & 0x5812631a5cf5d3ed), u64(0x0))
|
||||
x12, x13 := bits.add_u64(x3, (x9 & 0x14def9dea2f79cd6), u64(fiat.u1(x11)))
|
||||
x14, x15 := bits.add_u64(x5, u64(0x0), u64(fiat.u1(x13)))
|
||||
x16, _ := bits.add_u64(x7, (x9 & 0x1000000000000000), u64(fiat.u1(x15)))
|
||||
out1[0] = x10
|
||||
out1[1] = x12
|
||||
out1[2] = x14
|
||||
out1[3] = x16
|
||||
}
|
||||
|
||||
fe_opp :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) {
|
||||
x1, x2 := bits.sub_u64(u64(0x0), arg1[0], u64(0x0))
|
||||
x3, x4 := bits.sub_u64(u64(0x0), arg1[1], u64(fiat.u1(x2)))
|
||||
x5, x6 := bits.sub_u64(u64(0x0), arg1[2], u64(fiat.u1(x4)))
|
||||
x7, x8 := bits.sub_u64(u64(0x0), arg1[3], u64(fiat.u1(x6)))
|
||||
x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff)
|
||||
x10, x11 := bits.add_u64(x1, (x9 & 0x5812631a5cf5d3ed), u64(0x0))
|
||||
x12, x13 := bits.add_u64(x3, (x9 & 0x14def9dea2f79cd6), u64(fiat.u1(x11)))
|
||||
x14, x15 := bits.add_u64(x5, u64(0x0), u64(fiat.u1(x13)))
|
||||
x16, _ := bits.add_u64(x7, (x9 & 0x1000000000000000), u64(fiat.u1(x15)))
|
||||
out1[0] = x10
|
||||
out1[1] = x12
|
||||
out1[2] = x14
|
||||
out1[3] = x16
|
||||
}
|
||||
|
||||
fe_one :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) {
|
||||
out1[0] = 0xd6ec31748d98951d
|
||||
out1[1] = 0xc6ef5bf4737dcf70
|
||||
out1[2] = 0xfffffffffffffffe
|
||||
out1[3] = 0xfffffffffffffff
|
||||
}
|
||||
|
||||
fe_non_zero :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> u64 {
|
||||
return arg1[0] | (arg1[1] | (arg1[2] | arg1[3]))
|
||||
}
|
||||
|
||||
@(optimization_mode = "none")
|
||||
fe_cond_assign :: #force_no_inline proc "contextless" (
|
||||
out1, arg1: ^Montgomery_Domain_Field_Element,
|
||||
arg2: int,
|
||||
) {
|
||||
x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0])
|
||||
x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1])
|
||||
x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2])
|
||||
x4 := fiat.cmovznz_u64(fiat.u1(arg2), out1[3], arg1[3])
|
||||
out1[0] = x1
|
||||
out1[1] = x2
|
||||
out1[2] = x3
|
||||
out1[3] = x4
|
||||
}
|
||||
|
||||
fe_from_montgomery :: proc "contextless" (
|
||||
out1: ^Non_Montgomery_Domain_Field_Element,
|
||||
arg1: ^Montgomery_Domain_Field_Element,
|
||||
) {
|
||||
x1 := arg1[0]
|
||||
_, x2 := bits.mul_u64(x1, 0xd2b51da312547e1b)
|
||||
x5, x4 := bits.mul_u64(x2, 0x1000000000000000)
|
||||
x7, x6 := bits.mul_u64(x2, 0x14def9dea2f79cd6)
|
||||
x9, x8 := bits.mul_u64(x2, 0x5812631a5cf5d3ed)
|
||||
x10, x11 := bits.add_u64(x9, x6, u64(0x0))
|
||||
_, x13 := bits.add_u64(x1, x8, u64(0x0))
|
||||
x14, x15 := bits.add_u64(u64(0x0), x10, u64(fiat.u1(x13)))
|
||||
x16, x17 := bits.add_u64(x14, arg1[1], u64(0x0))
|
||||
_, x18 := bits.mul_u64(x16, 0xd2b51da312547e1b)
|
||||
x21, x20 := bits.mul_u64(x18, 0x1000000000000000)
|
||||
x23, x22 := bits.mul_u64(x18, 0x14def9dea2f79cd6)
|
||||
x25, x24 := bits.mul_u64(x18, 0x5812631a5cf5d3ed)
|
||||
x26, x27 := bits.add_u64(x25, x22, u64(0x0))
|
||||
_, x29 := bits.add_u64(x16, x24, u64(0x0))
|
||||
x30, x31 := bits.add_u64(
|
||||
(u64(fiat.u1(x17)) + (u64(fiat.u1(x15)) + (u64(fiat.u1(x11)) + x7))),
|
||||
x26,
|
||||
u64(fiat.u1(x29)),
|
||||
)
|
||||
x32, x33 := bits.add_u64(x4, (u64(fiat.u1(x27)) + x23), u64(fiat.u1(x31)))
|
||||
x34, x35 := bits.add_u64(x5, x20, u64(fiat.u1(x33)))
|
||||
x36, x37 := bits.add_u64(x30, arg1[2], u64(0x0))
|
||||
x38, x39 := bits.add_u64(x32, u64(0x0), u64(fiat.u1(x37)))
|
||||
x40, x41 := bits.add_u64(x34, u64(0x0), u64(fiat.u1(x39)))
|
||||
_, x42 := bits.mul_u64(x36, 0xd2b51da312547e1b)
|
||||
x45, x44 := bits.mul_u64(x42, 0x1000000000000000)
|
||||
x47, x46 := bits.mul_u64(x42, 0x14def9dea2f79cd6)
|
||||
x49, x48 := bits.mul_u64(x42, 0x5812631a5cf5d3ed)
|
||||
x50, x51 := bits.add_u64(x49, x46, u64(0x0))
|
||||
_, x53 := bits.add_u64(x36, x48, u64(0x0))
|
||||
x54, x55 := bits.add_u64(x38, x50, u64(fiat.u1(x53)))
|
||||
x56, x57 := bits.add_u64(x40, (u64(fiat.u1(x51)) + x47), u64(fiat.u1(x55)))
|
||||
x58, x59 := bits.add_u64(
|
||||
(u64(fiat.u1(x41)) + (u64(fiat.u1(x35)) + x21)),
|
||||
x44,
|
||||
u64(fiat.u1(x57)),
|
||||
)
|
||||
x60, x61 := bits.add_u64(x54, arg1[3], u64(0x0))
|
||||
x62, x63 := bits.add_u64(x56, u64(0x0), u64(fiat.u1(x61)))
|
||||
x64, x65 := bits.add_u64(x58, u64(0x0), u64(fiat.u1(x63)))
|
||||
_, x66 := bits.mul_u64(x60, 0xd2b51da312547e1b)
|
||||
x69, x68 := bits.mul_u64(x66, 0x1000000000000000)
|
||||
x71, x70 := bits.mul_u64(x66, 0x14def9dea2f79cd6)
|
||||
x73, x72 := bits.mul_u64(x66, 0x5812631a5cf5d3ed)
|
||||
x74, x75 := bits.add_u64(x73, x70, u64(0x0))
|
||||
_, x77 := bits.add_u64(x60, x72, u64(0x0))
|
||||
x78, x79 := bits.add_u64(x62, x74, u64(fiat.u1(x77)))
|
||||
x80, x81 := bits.add_u64(x64, (u64(fiat.u1(x75)) + x71), u64(fiat.u1(x79)))
|
||||
x82, x83 := bits.add_u64(
|
||||
(u64(fiat.u1(x65)) + (u64(fiat.u1(x59)) + x45)),
|
||||
x68,
|
||||
u64(fiat.u1(x81)),
|
||||
)
|
||||
x84 := (u64(fiat.u1(x83)) + x69)
|
||||
x85, x86 := bits.sub_u64(x78, 0x5812631a5cf5d3ed, u64(0x0))
|
||||
x87, x88 := bits.sub_u64(x80, 0x14def9dea2f79cd6, u64(fiat.u1(x86)))
|
||||
x89, x90 := bits.sub_u64(x82, u64(0x0), u64(fiat.u1(x88)))
|
||||
x91, x92 := bits.sub_u64(x84, 0x1000000000000000, u64(fiat.u1(x90)))
|
||||
_, x94 := bits.sub_u64(u64(0x0), u64(0x0), u64(fiat.u1(x92)))
|
||||
x95 := fiat.cmovznz_u64(fiat.u1(x94), x85, x78)
|
||||
x96 := fiat.cmovznz_u64(fiat.u1(x94), x87, x80)
|
||||
x97 := fiat.cmovznz_u64(fiat.u1(x94), x89, x82)
|
||||
x98 := fiat.cmovznz_u64(fiat.u1(x94), x91, x84)
|
||||
out1[0] = x95
|
||||
out1[1] = x96
|
||||
out1[2] = x97
|
||||
out1[3] = x98
|
||||
}
|
||||
|
||||
fe_to_montgomery :: proc "contextless" (
|
||||
out1: ^Montgomery_Domain_Field_Element,
|
||||
arg1: ^Non_Montgomery_Domain_Field_Element,
|
||||
) {
|
||||
x1 := arg1[1]
|
||||
x2 := arg1[2]
|
||||
x3 := arg1[3]
|
||||
x4 := arg1[0]
|
||||
x6, x5 := bits.mul_u64(x4, 0x399411b7c309a3d)
|
||||
x8, x7 := bits.mul_u64(x4, 0xceec73d217f5be65)
|
||||
x10, x9 := bits.mul_u64(x4, 0xd00e1ba768859347)
|
||||
x12, x11 := bits.mul_u64(x4, 0xa40611e3449c0f01)
|
||||
x13, x14 := bits.add_u64(x12, x9, u64(0x0))
|
||||
x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14)))
|
||||
x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16)))
|
||||
_, x19 := bits.mul_u64(x11, 0xd2b51da312547e1b)
|
||||
x22, x21 := bits.mul_u64(x19, 0x1000000000000000)
|
||||
x24, x23 := bits.mul_u64(x19, 0x14def9dea2f79cd6)
|
||||
x26, x25 := bits.mul_u64(x19, 0x5812631a5cf5d3ed)
|
||||
x27, x28 := bits.add_u64(x26, x23, u64(0x0))
|
||||
_, x30 := bits.add_u64(x11, x25, u64(0x0))
|
||||
x31, x32 := bits.add_u64(x13, x27, u64(fiat.u1(x30)))
|
||||
x33, x34 := bits.add_u64(x15, (u64(fiat.u1(x28)) + x24), u64(fiat.u1(x32)))
|
||||
x35, x36 := bits.add_u64(x17, x21, u64(fiat.u1(x34)))
|
||||
x38, x37 := bits.mul_u64(x1, 0x399411b7c309a3d)
|
||||
x40, x39 := bits.mul_u64(x1, 0xceec73d217f5be65)
|
||||
x42, x41 := bits.mul_u64(x1, 0xd00e1ba768859347)
|
||||
x44, x43 := bits.mul_u64(x1, 0xa40611e3449c0f01)
|
||||
x45, x46 := bits.add_u64(x44, x41, u64(0x0))
|
||||
x47, x48 := bits.add_u64(x42, x39, u64(fiat.u1(x46)))
|
||||
x49, x50 := bits.add_u64(x40, x37, u64(fiat.u1(x48)))
|
||||
x51, x52 := bits.add_u64(x31, x43, u64(0x0))
|
||||
x53, x54 := bits.add_u64(x33, x45, u64(fiat.u1(x52)))
|
||||
x55, x56 := bits.add_u64(x35, x47, u64(fiat.u1(x54)))
|
||||
x57, x58 := bits.add_u64(
|
||||
((u64(fiat.u1(x36)) + (u64(fiat.u1(x18)) + x6)) + x22),
|
||||
x49,
|
||||
u64(fiat.u1(x56)),
|
||||
)
|
||||
_, x59 := bits.mul_u64(x51, 0xd2b51da312547e1b)
|
||||
x62, x61 := bits.mul_u64(x59, 0x1000000000000000)
|
||||
x64, x63 := bits.mul_u64(x59, 0x14def9dea2f79cd6)
|
||||
x66, x65 := bits.mul_u64(x59, 0x5812631a5cf5d3ed)
|
||||
x67, x68 := bits.add_u64(x66, x63, u64(0x0))
|
||||
_, x70 := bits.add_u64(x51, x65, u64(0x0))
|
||||
x71, x72 := bits.add_u64(x53, x67, u64(fiat.u1(x70)))
|
||||
x73, x74 := bits.add_u64(x55, (u64(fiat.u1(x68)) + x64), u64(fiat.u1(x72)))
|
||||
x75, x76 := bits.add_u64(x57, x61, u64(fiat.u1(x74)))
|
||||
x78, x77 := bits.mul_u64(x2, 0x399411b7c309a3d)
|
||||
x80, x79 := bits.mul_u64(x2, 0xceec73d217f5be65)
|
||||
x82, x81 := bits.mul_u64(x2, 0xd00e1ba768859347)
|
||||
x84, x83 := bits.mul_u64(x2, 0xa40611e3449c0f01)
|
||||
x85, x86 := bits.add_u64(x84, x81, u64(0x0))
|
||||
x87, x88 := bits.add_u64(x82, x79, u64(fiat.u1(x86)))
|
||||
x89, x90 := bits.add_u64(x80, x77, u64(fiat.u1(x88)))
|
||||
x91, x92 := bits.add_u64(x71, x83, u64(0x0))
|
||||
x93, x94 := bits.add_u64(x73, x85, u64(fiat.u1(x92)))
|
||||
x95, x96 := bits.add_u64(x75, x87, u64(fiat.u1(x94)))
|
||||
x97, x98 := bits.add_u64(
|
||||
((u64(fiat.u1(x76)) + (u64(fiat.u1(x58)) + (u64(fiat.u1(x50)) + x38))) + x62),
|
||||
x89,
|
||||
u64(fiat.u1(x96)),
|
||||
)
|
||||
_, x99 := bits.mul_u64(x91, 0xd2b51da312547e1b)
|
||||
x102, x101 := bits.mul_u64(x99, 0x1000000000000000)
|
||||
x104, x103 := bits.mul_u64(x99, 0x14def9dea2f79cd6)
|
||||
x106, x105 := bits.mul_u64(x99, 0x5812631a5cf5d3ed)
|
||||
x107, x108 := bits.add_u64(x106, x103, u64(0x0))
|
||||
_, x110 := bits.add_u64(x91, x105, u64(0x0))
|
||||
x111, x112 := bits.add_u64(x93, x107, u64(fiat.u1(x110)))
|
||||
x113, x114 := bits.add_u64(x95, (u64(fiat.u1(x108)) + x104), u64(fiat.u1(x112)))
|
||||
x115, x116 := bits.add_u64(x97, x101, u64(fiat.u1(x114)))
|
||||
x118, x117 := bits.mul_u64(x3, 0x399411b7c309a3d)
|
||||
x120, x119 := bits.mul_u64(x3, 0xceec73d217f5be65)
|
||||
x122, x121 := bits.mul_u64(x3, 0xd00e1ba768859347)
|
||||
x124, x123 := bits.mul_u64(x3, 0xa40611e3449c0f01)
|
||||
x125, x126 := bits.add_u64(x124, x121, u64(0x0))
|
||||
x127, x128 := bits.add_u64(x122, x119, u64(fiat.u1(x126)))
|
||||
x129, x130 := bits.add_u64(x120, x117, u64(fiat.u1(x128)))
|
||||
x131, x132 := bits.add_u64(x111, x123, u64(0x0))
|
||||
x133, x134 := bits.add_u64(x113, x125, u64(fiat.u1(x132)))
|
||||
x135, x136 := bits.add_u64(x115, x127, u64(fiat.u1(x134)))
|
||||
x137, x138 := bits.add_u64(
|
||||
((u64(fiat.u1(x116)) + (u64(fiat.u1(x98)) + (u64(fiat.u1(x90)) + x78))) + x102),
|
||||
x129,
|
||||
u64(fiat.u1(x136)),
|
||||
)
|
||||
_, x139 := bits.mul_u64(x131, 0xd2b51da312547e1b)
|
||||
x142, x141 := bits.mul_u64(x139, 0x1000000000000000)
|
||||
x144, x143 := bits.mul_u64(x139, 0x14def9dea2f79cd6)
|
||||
x146, x145 := bits.mul_u64(x139, 0x5812631a5cf5d3ed)
|
||||
x147, x148 := bits.add_u64(x146, x143, u64(0x0))
|
||||
_, x150 := bits.add_u64(x131, x145, u64(0x0))
|
||||
x151, x152 := bits.add_u64(x133, x147, u64(fiat.u1(x150)))
|
||||
x153, x154 := bits.add_u64(x135, (u64(fiat.u1(x148)) + x144), u64(fiat.u1(x152)))
|
||||
x155, x156 := bits.add_u64(x137, x141, u64(fiat.u1(x154)))
|
||||
x157 := ((u64(fiat.u1(x156)) + (u64(fiat.u1(x138)) + (u64(fiat.u1(x130)) + x118))) + x142)
|
||||
x158, x159 := bits.sub_u64(x151, 0x5812631a5cf5d3ed, u64(0x0))
|
||||
x160, x161 := bits.sub_u64(x153, 0x14def9dea2f79cd6, u64(fiat.u1(x159)))
|
||||
x162, x163 := bits.sub_u64(x155, u64(0x0), u64(fiat.u1(x161)))
|
||||
x164, x165 := bits.sub_u64(x157, 0x1000000000000000, u64(fiat.u1(x163)))
|
||||
_, x167 := bits.sub_u64(u64(0x0), u64(0x0), u64(fiat.u1(x165)))
|
||||
x168 := fiat.cmovznz_u64(fiat.u1(x167), x158, x151)
|
||||
x169 := fiat.cmovznz_u64(fiat.u1(x167), x160, x153)
|
||||
x170 := fiat.cmovznz_u64(fiat.u1(x167), x162, x155)
|
||||
x171 := fiat.cmovznz_u64(fiat.u1(x167), x164, x157)
|
||||
out1[0] = x168
|
||||
out1[1] = x169
|
||||
out1[2] = x170
|
||||
out1[3] = x171
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
package crypto implements a selection of cryptography algorithms and useful
|
||||
helper routines.
|
||||
*/
|
||||
package crypto
|
||||
|
||||
import "core:mem"
|
||||
@@ -51,3 +55,9 @@ rand_bytes :: proc (dst: []byte) {
|
||||
|
||||
_rand_bytes(dst)
|
||||
}
|
||||
|
||||
// has_rand_bytes returns true iff the target has support for accessing the
|
||||
// system entropty source.
|
||||
has_rand_bytes :: proc () -> bool {
|
||||
return _has_rand_bytes()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
package ed25519 implements the Ed25519 EdDSA signature algorithm.
|
||||
|
||||
See:
|
||||
- https://datatracker.ietf.org/doc/html/rfc8032
|
||||
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
|
||||
- https://eprint.iacr.org/2020/1244.pdf
|
||||
*/
|
||||
package ed25519
|
||||
|
||||
import "core:crypto"
|
||||
import grp "core:crypto/_edwards25519"
|
||||
import "core:crypto/sha2"
|
||||
import "core:mem"
|
||||
|
||||
// PRIVATE_KEY_SIZE is the byte-encoded private key size.
|
||||
PRIVATE_KEY_SIZE :: 32
|
||||
// PUBLIC_KEY_SIZE is the byte-encoded public key size.
|
||||
PUBLIC_KEY_SIZE :: 32
|
||||
// SIGNATURE_SIZE is the byte-encoded signature size.
|
||||
SIGNATURE_SIZE :: 64
|
||||
|
||||
@(private)
|
||||
NONCE_SIZE :: 32
|
||||
|
||||
// Private_Key is an Ed25519 private key.
|
||||
Private_Key :: struct {
|
||||
// WARNING: All of the members are to be treated as internal (ie:
|
||||
// the Private_Key structure is intended to be opaque). There are
|
||||
// subtle vulnerabilities that can be introduced if the internal
|
||||
// values are allowed to be altered.
|
||||
//
|
||||
// See: https://github.com/MystenLabs/ed25519-unsafe-libs
|
||||
_b: [PRIVATE_KEY_SIZE]byte,
|
||||
_s: grp.Scalar,
|
||||
_nonce: [NONCE_SIZE]byte,
|
||||
_pub_key: Public_Key,
|
||||
_is_initialized: bool,
|
||||
}
|
||||
|
||||
// Public_Key is an Ed25519 public key.
|
||||
Public_Key :: struct {
|
||||
// WARNING: All of the members are to be treated as internal (ie:
|
||||
// the Public_Key structure is intended to be opaque).
|
||||
_b: [PUBLIC_KEY_SIZE]byte,
|
||||
_neg_A: grp.Group_Element,
|
||||
_is_valid: bool,
|
||||
_is_initialized: bool,
|
||||
}
|
||||
|
||||
// private_key_set_bytes decodes a byte-encoded private key, and returns
|
||||
// true iff the operation was successful.
|
||||
private_key_set_bytes :: proc(priv_key: ^Private_Key, b: []byte) -> bool {
|
||||
if len(b) != PRIVATE_KEY_SIZE {
|
||||
return false
|
||||
}
|
||||
|
||||
// Derive the private key.
|
||||
ctx: sha2.Context_512 = ---
|
||||
h_bytes: [sha2.DIGEST_SIZE_512]byte = ---
|
||||
sha2.init_512(&ctx)
|
||||
sha2.update(&ctx, b)
|
||||
sha2.final(&ctx, h_bytes[:])
|
||||
|
||||
copy(priv_key._b[:], b)
|
||||
copy(priv_key._nonce[:], h_bytes[32:])
|
||||
grp.sc_set_bytes_rfc8032(&priv_key._s, h_bytes[:32])
|
||||
|
||||
// Derive the corresponding public key.
|
||||
A: grp.Group_Element = ---
|
||||
grp.ge_scalarmult_basepoint(&A, &priv_key._s)
|
||||
grp.ge_bytes(&A, priv_key._pub_key._b[:])
|
||||
grp.ge_negate(&priv_key._pub_key._neg_A, &A)
|
||||
priv_key._pub_key._is_valid = !grp.ge_is_small_order(&A)
|
||||
priv_key._pub_key._is_initialized = true
|
||||
|
||||
priv_key._is_initialized = true
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// private_key_bytes sets dst to byte-encoding of priv_key.
|
||||
private_key_bytes :: proc(priv_key: ^Private_Key, dst: []byte) {
|
||||
if !priv_key._is_initialized {
|
||||
panic("crypto/ed25519: uninitialized private key")
|
||||
}
|
||||
if len(dst) != PRIVATE_KEY_SIZE {
|
||||
panic("crypto/ed25519: invalid destination size")
|
||||
}
|
||||
|
||||
copy(dst, priv_key._b[:])
|
||||
}
|
||||
|
||||
// private_key_clear clears priv_key to the uninitialized state.
|
||||
private_key_clear :: proc "contextless" (priv_key: ^Private_Key) {
|
||||
mem.zero_explicit(priv_key, size_of(Private_Key))
|
||||
}
|
||||
|
||||
// sign writes the signature by priv_key over msg to sig.
|
||||
sign :: proc(priv_key: ^Private_Key, msg, sig: []byte) {
|
||||
if !priv_key._is_initialized {
|
||||
panic("crypto/ed25519: uninitialized private key")
|
||||
}
|
||||
if len(sig) != SIGNATURE_SIZE {
|
||||
panic("crypto/ed25519: invalid destination size")
|
||||
}
|
||||
|
||||
// 1. Compute the hash of the private key d, H(d) = (h_0, h_1, ..., h_2b-1)
|
||||
// using SHA-512 for Ed25519. H(d) may be precomputed.
|
||||
//
|
||||
// 2. Using the second half of the digest hdigest2 = hb || ... || h2b-1,
|
||||
// define:
|
||||
//
|
||||
// 2.1 For Ed25519, r = SHA-512(hdigest2 || M); Interpret r as a
|
||||
// 64-octet little-endian integer.
|
||||
ctx: sha2.Context_512 = ---
|
||||
digest_bytes: [sha2.DIGEST_SIZE_512]byte = ---
|
||||
sha2.init_512(&ctx)
|
||||
sha2.update(&ctx, priv_key._nonce[:])
|
||||
sha2.update(&ctx, msg)
|
||||
sha2.final(&ctx, digest_bytes[:])
|
||||
|
||||
r: grp.Scalar = ---
|
||||
grp.sc_set_bytes_wide(&r, &digest_bytes)
|
||||
|
||||
// 3. Compute the point [r]G. The octet string R is the encoding of
|
||||
// the point [r]G.
|
||||
R: grp.Group_Element = ---
|
||||
R_bytes := sig[:32]
|
||||
grp.ge_scalarmult_basepoint(&R, &r)
|
||||
grp.ge_bytes(&R, R_bytes)
|
||||
|
||||
// 4. Derive s from H(d) as in the key pair generation algorithm.
|
||||
// Use octet strings R, Q, and M to define:
|
||||
//
|
||||
// 4.1 For Ed25519, digest = SHA-512(R || Q || M).
|
||||
// Interpret digest as a little-endian integer.
|
||||
sha2.init_512(&ctx)
|
||||
sha2.update(&ctx, R_bytes)
|
||||
sha2.update(&ctx, priv_key._pub_key._b[:]) // Q in NIST terminology.
|
||||
sha2.update(&ctx, msg)
|
||||
sha2.final(&ctx, digest_bytes[:])
|
||||
|
||||
sc: grp.Scalar = --- // `digest` in NIST terminology.
|
||||
grp.sc_set_bytes_wide(&sc, &digest_bytes)
|
||||
|
||||
// 5. Compute S = (r + digest × s) mod n. The octet string S is the
|
||||
// encoding of the resultant integer.
|
||||
grp.sc_mul(&sc, &sc, &priv_key._s)
|
||||
grp.sc_add(&sc, &sc, &r)
|
||||
|
||||
// 6. Form the signature as the concatenation of the octet strings
|
||||
// R and S.
|
||||
grp.sc_bytes(sig[32:], &sc)
|
||||
|
||||
grp.sc_clear(&r)
|
||||
}
|
||||
|
||||
// public_key_set_bytes decodes a byte-encoded public key, and returns
|
||||
// true iff the operation was successful.
|
||||
public_key_set_bytes :: proc "contextless" (pub_key: ^Public_Key, b: []byte) -> bool {
|
||||
if len(b) != PUBLIC_KEY_SIZE {
|
||||
return false
|
||||
}
|
||||
|
||||
A: grp.Group_Element = ---
|
||||
if !grp.ge_set_bytes(&A, b) {
|
||||
return false
|
||||
}
|
||||
|
||||
copy(pub_key._b[:], b)
|
||||
grp.ge_negate(&pub_key._neg_A, &A)
|
||||
pub_key._is_valid = !grp.ge_is_small_order(&A)
|
||||
pub_key._is_initialized = true
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// public_key_set_priv sets pub_key to the public component of priv_key.
|
||||
public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) {
|
||||
if !priv_key._is_initialized {
|
||||
panic("crypto/ed25519: uninitialized public key")
|
||||
}
|
||||
|
||||
src := &priv_key._pub_key
|
||||
copy(pub_key._b[:], src._b[:])
|
||||
grp.ge_set(&pub_key._neg_A, &src._neg_A)
|
||||
pub_key._is_valid = src._is_valid
|
||||
pub_key._is_initialized = src._is_initialized
|
||||
}
|
||||
|
||||
// public_key_bytes sets dst to byte-encoding of pub_key.
|
||||
public_key_bytes :: proc(pub_key: ^Public_Key, dst: []byte) {
|
||||
if !pub_key._is_initialized {
|
||||
panic("crypto/ed25519: uninitialized public key")
|
||||
}
|
||||
if len(dst) != PUBLIC_KEY_SIZE {
|
||||
panic("crypto/ed25519: invalid destination size")
|
||||
}
|
||||
|
||||
copy(dst, pub_key._b[:])
|
||||
}
|
||||
|
||||
// public_key_equal returns true iff pub_key is equal to other.
|
||||
public_key_equal :: proc(pub_key, other: ^Public_Key) -> bool {
|
||||
if !pub_key._is_initialized || !other._is_initialized {
|
||||
panic("crypto/ed25519: uninitialized public key")
|
||||
}
|
||||
|
||||
return crypto.compare_constant_time(pub_key._b[:], other._b[:]) == 1
|
||||
}
|
||||
|
||||
// verify returns true iff sig is a valid signature by pub_key over msg.
|
||||
//
|
||||
// The optional `allow_small_order_A` parameter will make this
|
||||
// implementation strictly compatible with FIPS 186-5, at the expense of
|
||||
// SBS-security. Doing so is NOT recommended, and the disallowed
|
||||
// public keys all have a known discrete-log.
|
||||
verify :: proc(pub_key: ^Public_Key, msg, sig: []byte, allow_small_order_A := false) -> bool {
|
||||
switch {
|
||||
case !pub_key._is_initialized:
|
||||
return false
|
||||
case len(sig) != SIGNATURE_SIZE:
|
||||
return false
|
||||
}
|
||||
|
||||
// TLDR: Just use ristretto255.
|
||||
//
|
||||
// While there are two "standards" for EdDSA, existing implementations
|
||||
// diverge (sometimes dramatically). This implementation opts for
|
||||
// "Algorithm 2" from "Taming the Many EdDSAs", which provides the
|
||||
// strongest notion of security (SUF-CMA + SBS).
|
||||
//
|
||||
// The relevant properties are:
|
||||
// - Reject non-canonical S.
|
||||
// - Reject non-canonical A/R.
|
||||
// - Reject small-order A (Extra non-standard check).
|
||||
// - Cofactored verification equation.
|
||||
//
|
||||
// There are 19 possible non-canonical group element encodings of
|
||||
// which:
|
||||
// - 2 are small order
|
||||
// - 10 are mixed order
|
||||
// - 7 are not on the curve
|
||||
//
|
||||
// While historical implementations have been lax about enforcing
|
||||
// that A/R are canonically encoded, that behavior is mandated by
|
||||
// both the RFC and FIPS specification. No valid key generation
|
||||
// or sign implementation will ever produce non-canonically encoded
|
||||
// public keys or signatures.
|
||||
//
|
||||
// There are 8 small-order group elements, 1 which is in the
|
||||
// prime-order sub-group, and thus the probability that a properly
|
||||
// generated A is small-order is cryptographically insignificant.
|
||||
//
|
||||
// While both the RFC and FIPS standard allow for either the
|
||||
// cofactored or non-cofactored equation. It is possible to
|
||||
// artificially produce signatures that are valid for the former
|
||||
// but not the latter. This will NEVER occur with a valid sign
|
||||
// implementation. The choice of the latter is to be compatible
|
||||
// with ABGLSV-Pornin, batch verification, and FROST (among other
|
||||
// things).
|
||||
|
||||
s_bytes, r_bytes := sig[32:], sig[:32]
|
||||
|
||||
// 1. Reject the signature if S is not in the range [0, L).
|
||||
s: grp.Scalar = ---
|
||||
if !grp.sc_set_bytes(&s, s_bytes) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 2. Reject the signature if the public key A is one of 8 small
|
||||
// order points.
|
||||
//
|
||||
// As this check is optional and not part of the standard, we allow
|
||||
// the caller to bypass it if desired. Disabling the check makes
|
||||
// the scheme NOT SBS-secure.
|
||||
if !pub_key._is_valid && !allow_small_order_A {
|
||||
return false
|
||||
}
|
||||
|
||||
// 3. Reject the signature if A or R are non-canonical.
|
||||
//
|
||||
// Note: All initialized public keys are guaranteed to be canonical.
|
||||
neg_R: grp.Group_Element = ---
|
||||
if !grp.ge_set_bytes(&neg_R, r_bytes) {
|
||||
return false
|
||||
}
|
||||
grp.ge_negate(&neg_R, &neg_R)
|
||||
|
||||
// 4. Compute the hash SHA512(R||A||M) and reduce it mod L to get a
|
||||
// scalar h.
|
||||
ctx: sha2.Context_512 = ---
|
||||
h_bytes: [sha2.DIGEST_SIZE_512]byte = ---
|
||||
sha2.init_512(&ctx)
|
||||
sha2.update(&ctx, r_bytes)
|
||||
sha2.update(&ctx, pub_key._b[:])
|
||||
sha2.update(&ctx, msg)
|
||||
sha2.final(&ctx, h_bytes[:])
|
||||
|
||||
h: grp.Scalar = ---
|
||||
grp.sc_set_bytes_wide(&h, &h_bytes)
|
||||
|
||||
// 5. Accept if 8(s * G) - 8R - 8(h * A) = 0
|
||||
//
|
||||
// > first compute V = SB − R − hA and then accept if V is one of
|
||||
// > 8 small order points (or alternatively compute 8V with 3
|
||||
// > doublings and check against the neutral element)
|
||||
V: grp.Group_Element = ---
|
||||
grp.ge_double_scalarmult_basepoint_vartime(&V, &h, &pub_key._neg_A, &s)
|
||||
grp.ge_add(&V, &V, &neg_R)
|
||||
|
||||
return grp.ge_is_small_order(&V)
|
||||
}
|
||||
@@ -168,7 +168,7 @@ reset :: proc(ctx: ^Context) {
|
||||
}
|
||||
|
||||
@(private)
|
||||
_blocks :: proc(ctx: ^Context, msg: []byte, final := false) {
|
||||
_blocks :: proc "contextless" (ctx: ^Context, msg: []byte, final := false) {
|
||||
n: field.Tight_Field_Element = ---
|
||||
final_byte := byte(!final)
|
||||
|
||||
|
||||
@@ -10,3 +10,7 @@ foreign libc {
|
||||
_rand_bytes :: proc(dst: []byte) {
|
||||
arc4random_buf(raw_data(dst), len(dst))
|
||||
}
|
||||
|
||||
_has_rand_bytes :: proc() -> bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package crypto
|
||||
|
||||
import "core:fmt"
|
||||
import "core:sys/darwin"
|
||||
|
||||
import CF "core:sys/darwin/CoreFoundation"
|
||||
import Sec "core:sys/darwin/Security"
|
||||
|
||||
_rand_bytes :: proc(dst: []byte) {
|
||||
res := darwin.SecRandomCopyBytes(count=len(dst), bytes=raw_data(dst))
|
||||
if res != .Success {
|
||||
msg := darwin.CFStringCopyToOdinString(darwin.SecCopyErrorMessageString(res))
|
||||
panic(fmt.tprintf("crypto/rand_bytes: SecRandomCopyBytes returned non-zero result: %v %s", res, msg))
|
||||
err := Sec.RandomCopyBytes(count=len(dst), bytes=raw_data(dst))
|
||||
if err != .Success {
|
||||
msg := CF.StringCopyToOdinString(Sec.CopyErrorMessageString(err))
|
||||
panic(fmt.tprintf("crypto/rand_bytes: SecRandomCopyBytes returned non-zero result: %v %s", err, msg))
|
||||
}
|
||||
}
|
||||
|
||||
_has_rand_bytes :: proc() -> bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -9,3 +9,7 @@ package crypto
|
||||
_rand_bytes :: proc(dst: []byte) {
|
||||
unimplemented("crypto: rand_bytes not supported on this OS")
|
||||
}
|
||||
|
||||
_has_rand_bytes :: proc() -> bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -18,3 +18,7 @@ _rand_bytes :: proc(dst: []byte) {
|
||||
dst = dst[to_read:]
|
||||
}
|
||||
}
|
||||
|
||||
_has_rand_bytes :: proc() -> bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -34,3 +34,7 @@ _rand_bytes :: proc (dst: []byte) {
|
||||
dst = dst[n_read:]
|
||||
}
|
||||
}
|
||||
|
||||
_has_rand_bytes :: proc() -> bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -21,3 +21,7 @@ _rand_bytes :: proc(dst: []byte) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_has_rand_bytes :: proc() -> bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,510 @@
|
||||
/*
|
||||
package ristretto255 implement the ristretto255 prime-order group.
|
||||
|
||||
See:
|
||||
- https://www.rfc-editor.org/rfc/rfc9496
|
||||
*/
|
||||
package ristretto255
|
||||
|
||||
import grp "core:crypto/_edwards25519"
|
||||
import field "core:crypto/_fiat/field_curve25519"
|
||||
import "core:mem"
|
||||
|
||||
// ELEMENT_SIZE is the size of a byte-encoded ristretto255 group element.
|
||||
ELEMENT_SIZE :: 32
|
||||
// WIDE_ELEMENT_SIZE is the side of a wide byte-encoded ristretto255
|
||||
// group element.
|
||||
WIDE_ELEMENT_SIZE :: 64
|
||||
|
||||
@(private)
|
||||
FE_NEG_ONE := field.Tight_Field_Element {
|
||||
2251799813685228,
|
||||
2251799813685247,
|
||||
2251799813685247,
|
||||
2251799813685247,
|
||||
2251799813685247,
|
||||
}
|
||||
@(private)
|
||||
FE_INVSQRT_A_MINUS_D := field.Tight_Field_Element {
|
||||
278908739862762,
|
||||
821645201101625,
|
||||
8113234426968,
|
||||
1777959178193151,
|
||||
2118520810568447,
|
||||
}
|
||||
@(private)
|
||||
FE_ONE_MINUS_D_SQ := field.Tight_Field_Element {
|
||||
1136626929484150,
|
||||
1998550399581263,
|
||||
496427632559748,
|
||||
118527312129759,
|
||||
45110755273534,
|
||||
}
|
||||
@(private)
|
||||
FE_D_MINUS_ONE_SQUARED := field.Tight_Field_Element {
|
||||
1507062230895904,
|
||||
1572317787530805,
|
||||
683053064812840,
|
||||
317374165784489,
|
||||
1572899562415810,
|
||||
}
|
||||
@(private)
|
||||
FE_SQRT_AD_MINUS_ONE := field.Tight_Field_Element {
|
||||
2241493124984347,
|
||||
425987919032274,
|
||||
2207028919301688,
|
||||
1220490630685848,
|
||||
974799131293748,
|
||||
}
|
||||
@(private)
|
||||
GE_IDENTITY := Group_Element{grp.GE_IDENTITY, true}
|
||||
|
||||
// Group_Element is a ristretto255 group element. The zero-initialized
|
||||
// value is invalid.
|
||||
Group_Element :: struct {
|
||||
// WARNING: While the internal representation is an Edwards25519
|
||||
// group element, this is not guaranteed to always be the case,
|
||||
// and your code *WILL* break if you mess with `_p`.
|
||||
_p: grp.Group_Element,
|
||||
_is_initialized: bool,
|
||||
}
|
||||
|
||||
// ge_clear clears ge to the uninitialized state.
|
||||
ge_clear :: proc "contextless" (ge: ^Group_Element) {
|
||||
mem.zero_explicit(ge, size_of(Group_Element))
|
||||
}
|
||||
|
||||
// ge_set sets `ge = a`.
|
||||
ge_set :: proc(ge, a: ^Group_Element) {
|
||||
_ge_assert_initialized([]^Group_Element{a})
|
||||
|
||||
grp.ge_set(&ge._p, &a._p)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_identity sets ge to the identity (neutral) element.
|
||||
ge_identity :: proc "contextless" (ge: ^Group_Element) {
|
||||
grp.ge_identity(&ge._p)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_generator sets ge to the group generator.
|
||||
ge_generator :: proc "contextless" (ge: ^Group_Element) {
|
||||
grp.ge_generator(&ge._p)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_set_bytes sets ge to the result of decoding b as a ristretto255
|
||||
// group element, and returns true on success.
|
||||
@(require_results)
|
||||
ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool {
|
||||
// 1. Interpret the string as an unsigned integer s in little-endian
|
||||
// representation. If the length of the string is not 32 bytes or
|
||||
// if the resulting value is >= p, decoding fails.
|
||||
//
|
||||
// 2. If IS_NEGATIVE(s) returns TRUE, decoding fails.
|
||||
|
||||
if len(b) != ELEMENT_SIZE {
|
||||
return false
|
||||
}
|
||||
if b[31] & 128 != 0 || b[0] & 1 != 0 {
|
||||
// Fail early if b is clearly > p, or negative.
|
||||
return false
|
||||
}
|
||||
|
||||
b_ := transmute(^[32]byte)(raw_data(b))
|
||||
|
||||
s: field.Tight_Field_Element = ---
|
||||
defer field.fe_clear(&s)
|
||||
|
||||
field.fe_from_bytes(&s, b_)
|
||||
if field.fe_equal_bytes(&s, b_) != 1 {
|
||||
// Reject non-canonical encodings of s.
|
||||
return false
|
||||
}
|
||||
|
||||
// 3. Process s as follows:
|
||||
v, u1, u2: field.Loose_Field_Element = ---, ---, ---
|
||||
tmp, u2_sqr: field.Tight_Field_Element = ---, ---
|
||||
|
||||
// ss = s^2
|
||||
// u1 = 1 - ss
|
||||
// u2 = 1 + ss
|
||||
// u2_sqr = u2^2
|
||||
field.fe_carry_square(&tmp, field.fe_relax_cast(&s))
|
||||
field.fe_sub(&u1, &field.FE_ONE, &tmp)
|
||||
field.fe_add(&u2, &field.FE_ONE, &tmp)
|
||||
field.fe_carry_square(&u2_sqr, &u2)
|
||||
|
||||
// v = -(D * u1^2) - u2_sqr
|
||||
field.fe_carry_square(&tmp, &u1)
|
||||
field.fe_carry_mul(&tmp, field.fe_relax_cast(&grp.FE_D), field.fe_relax_cast(&tmp))
|
||||
field.fe_carry_add(&tmp, &tmp, &u2_sqr)
|
||||
field.fe_opp(&v, &tmp)
|
||||
|
||||
// (was_square, invsqrt) = SQRT_RATIO_M1(1, v * u2_sqr)
|
||||
field.fe_carry_mul(&tmp, &v, field.fe_relax_cast(&u2_sqr))
|
||||
was_square := field.fe_carry_sqrt_ratio_m1(
|
||||
&tmp,
|
||||
field.fe_relax_cast(&field.FE_ONE),
|
||||
field.fe_relax_cast(&tmp),
|
||||
)
|
||||
|
||||
// den_x = invsqrt * u2
|
||||
// den_y = invsqrt * den_x * v
|
||||
x, y, t: field.Tight_Field_Element = ---, ---, ---
|
||||
field.fe_carry_mul(&x, field.fe_relax_cast(&tmp), &u2)
|
||||
field.fe_carry_mul(&y, field.fe_relax_cast(&tmp), field.fe_relax_cast(&x))
|
||||
field.fe_carry_mul(&y, field.fe_relax_cast(&y), &v)
|
||||
|
||||
// x = CT_ABS(2 * s * den_x)
|
||||
field.fe_carry_mul(&x, field.fe_relax_cast(&s), field.fe_relax_cast(&x))
|
||||
field.fe_carry_add(&x, &x, &x)
|
||||
field.fe_carry_abs(&x, &x)
|
||||
|
||||
// y = u1 * den_y
|
||||
field.fe_carry_mul(&y, &u1, field.fe_relax_cast(&y))
|
||||
|
||||
// t = x * y
|
||||
field.fe_carry_mul(&t, field.fe_relax_cast(&x), field.fe_relax_cast(&y))
|
||||
|
||||
field.fe_clear_vec([]^field.Loose_Field_Element{&v, &u1, &u2})
|
||||
field.fe_clear_vec([]^field.Tight_Field_Element{&tmp, &u2_sqr})
|
||||
defer field.fe_clear_vec([]^field.Tight_Field_Element{&x, &y, &t})
|
||||
|
||||
// 4. If was_square is FALSE, IS_NEGATIVE(t) returns TRUE, or y = 0,
|
||||
// decoding fails. Otherwise, return the group element represented
|
||||
// by the internal representation (x, y, 1, t) as the result of
|
||||
// decoding.
|
||||
|
||||
switch {
|
||||
case was_square == 0:
|
||||
// Not sure why the RFC doesn't have this just fail early.
|
||||
return false
|
||||
case field.fe_is_negative(&t) != 0:
|
||||
return false
|
||||
case field.fe_equal(&y, &field.FE_ZERO) != 0:
|
||||
return false
|
||||
}
|
||||
|
||||
field.fe_set(&ge._p.x, &x)
|
||||
field.fe_set(&ge._p.y, &y)
|
||||
field.fe_one(&ge._p.z)
|
||||
field.fe_set(&ge._p.t, &t)
|
||||
ge._is_initialized = true
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// ge_set_wide_bytes sets ge to the result of deriving a ristretto255
|
||||
// group element, from a wide (512-bit) byte string.
|
||||
ge_set_wide_bytes :: proc(ge: ^Group_Element, b: []byte) {
|
||||
if len(b) != WIDE_ELEMENT_SIZE {
|
||||
panic("crypto/ristretto255: invalid wide input size")
|
||||
}
|
||||
|
||||
// The element derivation function on an input string b proceeds as
|
||||
// follows:
|
||||
//
|
||||
// 1. Compute P1 as MAP(b[0:32]).
|
||||
// 2. Compute P2 as MAP(b[32:64]).
|
||||
// 3. Return P1 + P2.
|
||||
|
||||
p1, p2: Group_Element = ---, ---
|
||||
ge_map(&p1, b[0:32])
|
||||
ge_map(&p2, b[32:64])
|
||||
|
||||
ge_add(ge, &p1, &p2)
|
||||
|
||||
ge_clear(&p1)
|
||||
ge_clear(&p2)
|
||||
}
|
||||
|
||||
// ge_bytes sets dst to the canonical encoding of ge.
|
||||
ge_bytes :: proc(ge: ^Group_Element, dst: []byte) {
|
||||
_ge_assert_initialized([]^Group_Element{ge})
|
||||
if len(dst) != ELEMENT_SIZE {
|
||||
panic("crypto/ristretto255: invalid destination size")
|
||||
}
|
||||
|
||||
x0, y0, z0, t0 := &ge._p.x, &ge._p.y, &ge._p.z, &ge._p.t
|
||||
|
||||
// 1. Process the internal representation into a field element s as
|
||||
// follows:
|
||||
|
||||
// u1 = (z0 + y0) * (z0 - y0)
|
||||
// u2 = x0 * y0
|
||||
u1, u2: field.Tight_Field_Element = ---, ---
|
||||
tmp1, tmp2: field.Loose_Field_Element = ---, ---
|
||||
field.fe_add(&tmp1, z0, y0)
|
||||
field.fe_sub(&tmp2, z0, y0)
|
||||
field.fe_carry_mul(&u1, &tmp1, &tmp2)
|
||||
field.fe_carry_mul(&u2, field.fe_relax_cast(x0), field.fe_relax_cast(y0))
|
||||
|
||||
// Ignore was_square since this is always square.
|
||||
// (_, invsqrt) = SQRT_RATIO_M1(1, u1 * u2^2)
|
||||
tmp: field.Tight_Field_Element = ---
|
||||
field.fe_carry_square(&tmp, field.fe_relax_cast(&u2))
|
||||
field.fe_carry_mul(&tmp, field.fe_relax_cast(&u1), field.fe_relax_cast(&tmp))
|
||||
_ = field.fe_carry_sqrt_ratio_m1(
|
||||
&tmp,
|
||||
field.fe_relax_cast(&field.FE_ONE),
|
||||
field.fe_relax_cast(&tmp),
|
||||
)
|
||||
|
||||
// den1 = invsqrt * u1
|
||||
// den2 = invsqrt * u2
|
||||
// z_inv = den1 * den2 * t0
|
||||
den1, den2 := &u1, &u2
|
||||
z_inv: field.Tight_Field_Element = ---
|
||||
field.fe_carry_mul(den1, field.fe_relax_cast(&tmp), field.fe_relax_cast(&u1))
|
||||
field.fe_carry_mul(den2, field.fe_relax_cast(&tmp), field.fe_relax_cast(&u2))
|
||||
field.fe_carry_mul(&z_inv, field.fe_relax_cast(den1), field.fe_relax_cast(den2))
|
||||
field.fe_carry_mul(&z_inv, field.fe_relax_cast(&z_inv), field.fe_relax_cast(t0))
|
||||
|
||||
// rotate = IS_NEGATIVE(t0 * z_inv)
|
||||
// Note: Reordered from the RFC because invsqrt is no longer needed.
|
||||
field.fe_carry_mul(&tmp, field.fe_relax_cast(t0), field.fe_relax_cast(&z_inv))
|
||||
rotate := field.fe_is_negative(&tmp)
|
||||
|
||||
// ix0 = x0 * SQRT_M1
|
||||
// iy0 = y0 * SQRT_M1
|
||||
// enchanted_denominator = den1 * INVSQRT_A_MINUS_D
|
||||
ix0, iy0: field.Tight_Field_Element = ---, ---
|
||||
field.fe_carry_mul(&ix0, field.fe_relax_cast(x0), field.fe_relax_cast(&field.FE_SQRT_M1))
|
||||
field.fe_carry_mul(&iy0, field.fe_relax_cast(y0), field.fe_relax_cast(&field.FE_SQRT_M1))
|
||||
field.fe_carry_mul(&tmp, field.fe_relax_cast(den1), field.fe_relax_cast(&FE_INVSQRT_A_MINUS_D))
|
||||
|
||||
// Conditionally rotate x and y.
|
||||
// x = CT_SELECT(iy0 IF rotate ELSE x0)
|
||||
// y = CT_SELECT(ix0 IF rotate ELSE y0)
|
||||
// z = z0
|
||||
// den_inv = CT_SELECT(enchanted_denominator IF rotate ELSE den2)
|
||||
x, y: field.Tight_Field_Element = ---, ---
|
||||
field.fe_cond_select(&x, x0, &iy0, rotate)
|
||||
field.fe_cond_select(&y, y0, &ix0, rotate)
|
||||
field.fe_cond_select(&tmp, den2, &tmp, rotate)
|
||||
|
||||
// y = CT_SELECT(-y IF IS_NEGATIVE(x * z_inv) ELSE y)
|
||||
field.fe_carry_mul(&x, field.fe_relax_cast(&x), field.fe_relax_cast(&z_inv))
|
||||
field.fe_cond_negate(&y, &y, field.fe_is_negative(&x))
|
||||
|
||||
// s = CT_ABS(den_inv * (z - y))
|
||||
field.fe_sub(&tmp1, z0, &y)
|
||||
field.fe_carry_mul(&tmp, field.fe_relax_cast(&tmp), &tmp1)
|
||||
field.fe_carry_abs(&tmp, &tmp)
|
||||
|
||||
// 2. Return the 32-byte little-endian encoding of s. More
|
||||
// specifically, this is the encoding of the canonical
|
||||
// representation of s as an integer between 0 and p-1, inclusive.
|
||||
dst_ := transmute(^[32]byte)(raw_data(dst))
|
||||
field.fe_to_bytes(dst_, &tmp)
|
||||
|
||||
field.fe_clear_vec([]^field.Tight_Field_Element{&u1, &u2, &tmp, &z_inv, &ix0, &iy0, &x, &y})
|
||||
field.fe_clear_vec([]^field.Loose_Field_Element{&tmp1, &tmp2})
|
||||
}
|
||||
|
||||
// ge_add sets `ge = a + b`.
|
||||
ge_add :: proc(ge, a, b: ^Group_Element) {
|
||||
_ge_assert_initialized([]^Group_Element{a, b})
|
||||
|
||||
grp.ge_add(&ge._p, &a._p, &b._p)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_double sets `ge = a + a`.
|
||||
ge_double :: proc(ge, a: ^Group_Element) {
|
||||
_ge_assert_initialized([]^Group_Element{a})
|
||||
|
||||
grp.ge_double(&ge._p, &a._p)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_negate sets `ge = -a`.
|
||||
ge_negate :: proc(ge, a: ^Group_Element) {
|
||||
_ge_assert_initialized([]^Group_Element{a})
|
||||
|
||||
grp.ge_negate(&ge._p, &a._p)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_scalarmult sets `ge = A * sc`.
|
||||
ge_scalarmult :: proc(ge, A: ^Group_Element, sc: ^Scalar) {
|
||||
_ge_assert_initialized([]^Group_Element{A})
|
||||
|
||||
grp.ge_scalarmult(&ge._p, &A._p, sc)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_scalarmult_generator sets `ge = G * sc`
|
||||
ge_scalarmult_generator :: proc "contextless" (ge: ^Group_Element, sc: ^Scalar) {
|
||||
grp.ge_scalarmult_basepoint(&ge._p, sc)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_scalarmult_vartime sets `ge = A * sc` in variable time.
|
||||
ge_scalarmult_vartime :: proc(ge, A: ^Group_Element, sc: ^Scalar) {
|
||||
_ge_assert_initialized([]^Group_Element{A})
|
||||
|
||||
grp.ge_scalarmult_vartime(&ge._p, &A._p, sc)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_double_scalarmult_generator_vartime sets `ge = A * a + G * b` in variable
|
||||
// time.
|
||||
ge_double_scalarmult_generator_vartime :: proc(
|
||||
ge: ^Group_Element,
|
||||
a: ^Scalar,
|
||||
A: ^Group_Element,
|
||||
b: ^Scalar,
|
||||
) {
|
||||
_ge_assert_initialized([]^Group_Element{A})
|
||||
|
||||
grp.ge_double_scalarmult_basepoint_vartime(&ge._p, a, &A._p, b)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_cond_negate sets `ge = a` iff `ctrl == 0` and `ge = -a` iff `ctrl == 1`.
|
||||
// Behavior for all other values of ctrl are undefined,
|
||||
ge_cond_negate :: proc(ge, a: ^Group_Element, ctrl: int) {
|
||||
_ge_assert_initialized([]^Group_Element{a})
|
||||
|
||||
grp.ge_cond_negate(&ge._p, &a._p, ctrl)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_cond_assign sets `ge = ge` iff `ctrl == 0` and `ge = a` iff `ctrl == 1`.
|
||||
// Behavior for all other values of ctrl are undefined,
|
||||
ge_cond_assign :: proc(ge, a: ^Group_Element, ctrl: int) {
|
||||
_ge_assert_initialized([]^Group_Element{ge, a})
|
||||
|
||||
grp.ge_cond_assign(&ge._p, &a._p, ctrl)
|
||||
}
|
||||
|
||||
// ge_cond_select sets `ge = a` iff `ctrl == 0` and `ge = b` iff `ctrl == 1`.
|
||||
// Behavior for all other values of ctrl are undefined,
|
||||
ge_cond_select :: proc(ge, a, b: ^Group_Element, ctrl: int) {
|
||||
_ge_assert_initialized([]^Group_Element{a, b})
|
||||
|
||||
grp.ge_cond_select(&ge._p, &a._p, &b._p, ctrl)
|
||||
ge._is_initialized = true
|
||||
}
|
||||
|
||||
// ge_equal returns 1 iff `a == b`, and 0 otherwise.
|
||||
@(require_results)
|
||||
ge_equal :: proc(a, b: ^Group_Element) -> int {
|
||||
_ge_assert_initialized([]^Group_Element{a, b})
|
||||
|
||||
// CT_EQ(x1 * y2, y1 * x2) | CT_EQ(y1 * y2, x1 * x2)
|
||||
ax_by, ay_bx, ay_by, ax_bx: field.Tight_Field_Element = ---, ---, ---, ---
|
||||
field.fe_carry_mul(&ax_by, field.fe_relax_cast(&a._p.x), field.fe_relax_cast(&b._p.y))
|
||||
field.fe_carry_mul(&ay_bx, field.fe_relax_cast(&a._p.y), field.fe_relax_cast(&b._p.x))
|
||||
field.fe_carry_mul(&ay_by, field.fe_relax_cast(&a._p.y), field.fe_relax_cast(&b._p.y))
|
||||
field.fe_carry_mul(&ax_bx, field.fe_relax_cast(&a._p.x), field.fe_relax_cast(&b._p.x))
|
||||
|
||||
ret := field.fe_equal(&ax_by, &ay_bx) | field.fe_equal(&ay_by, &ax_bx)
|
||||
|
||||
field.fe_clear_vec([]^field.Tight_Field_Element{&ax_by, &ay_bx, &ay_by, &ax_bx})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// ge_is_identity returns 1 iff `ge` is the identity element, and 0 otherwise.
|
||||
@(require_results)
|
||||
ge_is_identity :: proc(ge: ^Group_Element) -> int {
|
||||
return ge_equal(ge, &GE_IDENTITY)
|
||||
}
|
||||
|
||||
@(private)
|
||||
ge_map :: proc "contextless" (ge: ^Group_Element, b: []byte) {
|
||||
b_ := transmute(^[32]byte)(raw_data(b))
|
||||
|
||||
// The MAP function is defined on 32-byte strings as:
|
||||
//
|
||||
// 1. Mask the most significant bit in the final byte of the string,
|
||||
// and interpret the string as an unsigned integer r in little-
|
||||
// endian representation. Reduce r modulo p to obtain a field
|
||||
// element t.
|
||||
// * Masking the most significant bit is equivalent to interpreting
|
||||
// the whole string as an unsigned integer in little-endian
|
||||
// representation and then reducing it modulo 2^255.
|
||||
t: field.Tight_Field_Element = ---
|
||||
field.fe_from_bytes(&t, b_)
|
||||
|
||||
// 2. Process t as follows:
|
||||
//
|
||||
// r = SQRT_M1 * t^2
|
||||
// u = (r + 1) * ONE_MINUS_D_SQ
|
||||
// v = (-1 - r*D) * (r + D)
|
||||
tmp1: field.Loose_Field_Element = ---
|
||||
r, u, v: field.Tight_Field_Element = ---, ---, ---
|
||||
|
||||
field.fe_carry_square(&r, field.fe_relax_cast(&t))
|
||||
field.fe_carry_mul(&r, field.fe_relax_cast(&field.FE_SQRT_M1), field.fe_relax_cast(&r))
|
||||
|
||||
field.fe_add(&tmp1, &field.FE_ONE, &r)
|
||||
field.fe_carry_mul(&u, &tmp1, field.fe_relax_cast(&FE_ONE_MINUS_D_SQ))
|
||||
|
||||
field.fe_carry_mul(&v, field.fe_relax_cast(&r), field.fe_relax_cast(&grp.FE_D))
|
||||
field.fe_carry_add(&v, &field.FE_ONE, &v)
|
||||
field.fe_carry_opp(&v, &v)
|
||||
field.fe_add(&tmp1, &r, &grp.FE_D)
|
||||
field.fe_carry_mul(&v, field.fe_relax_cast(&v), &tmp1)
|
||||
|
||||
// (was_square, s) = SQRT_RATIO_M1(u, v)
|
||||
// s_prime = -CT_ABS(s*t)
|
||||
// s = CT_SELECT(s IF was_square ELSE s_prime)
|
||||
// c = CT_SELECT(-1 IF was_square ELSE r)
|
||||
s, s_prime, c: field.Tight_Field_Element = ---, ---, ---
|
||||
was_square := field.fe_carry_sqrt_ratio_m1(
|
||||
&s,
|
||||
field.fe_relax_cast(&u),
|
||||
field.fe_relax_cast(&v),
|
||||
)
|
||||
field.fe_carry_mul(&s_prime, field.fe_relax_cast(&s), field.fe_relax_cast(&t))
|
||||
field.fe_carry_abs(&s_prime, &s_prime)
|
||||
field.fe_carry_opp(&s_prime, &s_prime)
|
||||
field.fe_cond_select(&s, &s_prime, &s, was_square)
|
||||
field.fe_cond_select(&c, &r, &FE_NEG_ONE, was_square)
|
||||
|
||||
// N = c * (r - 1) * D_MINUS_ONE_SQ - v
|
||||
N: field.Tight_Field_Element = ---
|
||||
field.fe_sub(&tmp1, &r, &field.FE_ONE)
|
||||
field.fe_carry_mul(&N, field.fe_relax_cast(&c), &tmp1)
|
||||
field.fe_carry_mul(&N, field.fe_relax_cast(&N), field.fe_relax_cast(&FE_D_MINUS_ONE_SQUARED))
|
||||
field.fe_carry_sub(&N, &N, &v)
|
||||
|
||||
// w0 = 2 * s * v
|
||||
// w1 = N * SQRT_AD_MINUS_ONE
|
||||
// w2 = 1 - s^2
|
||||
// w3 = 1 + s^2
|
||||
w0, w1: field.Tight_Field_Element = ---, ---
|
||||
w2, w3: field.Loose_Field_Element = ---, ---
|
||||
field.fe_carry_mul(&w0, field.fe_relax_cast(&s), field.fe_relax_cast(&v))
|
||||
field.fe_carry_add(&w0, &w0, &w0)
|
||||
field.fe_carry_mul(&w1, field.fe_relax_cast(&N), field.fe_relax_cast(&FE_SQRT_AD_MINUS_ONE))
|
||||
field.fe_carry_square(&s, field.fe_relax_cast(&s))
|
||||
field.fe_sub(&w2, &field.FE_ONE, &s)
|
||||
field.fe_add(&w3, &field.FE_ONE, &s)
|
||||
|
||||
// 3. Return the group element represented by the internal
|
||||
// representation (w0*w3, w2*w1, w1*w3, w0*w2).
|
||||
|
||||
field.fe_carry_mul(&ge._p.x, field.fe_relax_cast(&w0), &w3)
|
||||
field.fe_carry_mul(&ge._p.y, &w2, field.fe_relax_cast(&w1))
|
||||
field.fe_carry_mul(&ge._p.z, field.fe_relax_cast(&w1), &w3)
|
||||
field.fe_carry_mul(&ge._p.t, field.fe_relax_cast(&w0), &w2)
|
||||
ge._is_initialized = true
|
||||
|
||||
field.fe_clear_vec([]^field.Tight_Field_Element{&r, &u, &v, &s, &s_prime, &c, &N, &w0, &w1})
|
||||
field.fe_clear_vec([]^field.Loose_Field_Element{&tmp1, &w2, &w3})
|
||||
}
|
||||
|
||||
@(private)
|
||||
_ge_assert_initialized :: proc(ges: []^Group_Element) {
|
||||
for ge in ges {
|
||||
if !ge._is_initialized {
|
||||
panic("crypto/ristretto255: uninitialized group element")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package ristretto255
|
||||
|
||||
import grp "core:crypto/_edwards25519"
|
||||
|
||||
// SCALAR_SIZE is the size of a byte-encoded ristretto255 scalar.
|
||||
SCALAR_SIZE :: 32
|
||||
// WIDE_SCALAR_SIZE is the size of a wide byte-encoded ristretto255
|
||||
// scalar.
|
||||
WIDE_SCALAR_SIZE :: 64
|
||||
|
||||
// Scalar is a ristretto255 scalar. The zero-initialized value is valid,
|
||||
// and represents `0`.
|
||||
Scalar :: grp.Scalar
|
||||
|
||||
// sc_clear clears sc to the uninitialized state.
|
||||
sc_clear :: proc "contextless" (sc: ^Scalar) {
|
||||
grp.sc_clear(sc)
|
||||
}
|
||||
|
||||
// sc_set sets `sc = a`.
|
||||
sc_set :: proc "contextless" (sc, a: ^Scalar) {
|
||||
grp.sc_set(sc, a)
|
||||
}
|
||||
|
||||
// sc_set_u64 sets `sc = i`.
|
||||
sc_set_u64 :: proc "contextless" (sc: ^Scalar, i: u64) {
|
||||
grp.sc_set_u64(sc, i)
|
||||
}
|
||||
|
||||
// sc_set_bytes sets sc to the result of decoding b as a ristretto255
|
||||
// scalar, and returns true on success.
|
||||
@(require_results)
|
||||
sc_set_bytes :: proc(sc: ^Scalar, b: []byte) -> bool {
|
||||
if len(b) != SCALAR_SIZE {
|
||||
return false
|
||||
}
|
||||
|
||||
return grp.sc_set_bytes(sc, b)
|
||||
}
|
||||
|
||||
// sc_set_wide_bytes sets sc to the result of deriving a ristretto255
|
||||
// scalar, from a wide (512-bit) byte string by interpreting b as a
|
||||
// little-endian value, and reducing it mod the group order.
|
||||
sc_set_bytes_wide :: proc(sc: ^Scalar, b: []byte) {
|
||||
if len(b) != WIDE_SCALAR_SIZE {
|
||||
panic("crypto/ristretto255: invalid wide input size")
|
||||
}
|
||||
|
||||
b_ := transmute(^[WIDE_SCALAR_SIZE]byte)(raw_data(b))
|
||||
grp.sc_set_bytes_wide(sc, b_)
|
||||
}
|
||||
|
||||
// sc_bytes sets dst to the canonical encoding of sc.
|
||||
sc_bytes :: proc(sc: ^Scalar, dst: []byte) {
|
||||
if len(dst) != SCALAR_SIZE {
|
||||
panic("crypto/ristretto255: invalid destination size")
|
||||
}
|
||||
|
||||
grp.sc_bytes(dst, sc)
|
||||
}
|
||||
|
||||
// sc_add sets `sc = a + b`.
|
||||
sc_add :: proc "contextless" (sc, a, b: ^Scalar) {
|
||||
grp.sc_add(sc, a, b)
|
||||
}
|
||||
|
||||
// sc_sub sets `sc = a - b`.
|
||||
sc_sub :: proc "contextless" (sc, a, b: ^Scalar) {
|
||||
grp.sc_sub(sc, a, b)
|
||||
}
|
||||
|
||||
// sc_negate sets `sc = -a`.
|
||||
sc_negate :: proc "contextless" (sc, a: ^Scalar) {
|
||||
grp.sc_negate(sc, a)
|
||||
}
|
||||
|
||||
// sc_mul sets `sc = a * b`.
|
||||
sc_mul :: proc "contextless" (sc, a, b: ^Scalar) {
|
||||
grp.sc_mul(sc, a, b)
|
||||
}
|
||||
|
||||
// sc_square sets `sc = a^2`.
|
||||
sc_square :: proc "contextless" (sc, a: ^Scalar) {
|
||||
grp.sc_square(sc, a)
|
||||
}
|
||||
|
||||
// sc_cond_assign sets `sc = sc` iff `ctrl == 0` and `sc = a` iff `ctrl == 1`.
|
||||
// Behavior for all other values of ctrl are undefined,
|
||||
sc_cond_assign :: proc(sc, a: ^Scalar, ctrl: int) {
|
||||
grp.sc_cond_assign(sc, a, ctrl)
|
||||
}
|
||||
|
||||
// sc_equal returns 1 iff `a == b`, and 0 otherwise.
|
||||
@(require_results)
|
||||
sc_equal :: proc(a, b: ^Scalar) -> int {
|
||||
return grp.sc_equal(a, b)
|
||||
}
|
||||
@@ -27,7 +27,7 @@ _scalar_bit :: #force_inline proc "contextless" (s: ^[32]byte, i: int) -> u8 {
|
||||
}
|
||||
|
||||
@(private)
|
||||
_scalarmult :: proc(out, scalar, point: ^[32]byte) {
|
||||
_scalarmult :: proc "contextless" (out, scalar, point: ^[32]byte) {
|
||||
// Montgomery pseduo-multiplication taken from Monocypher.
|
||||
|
||||
// computes the scalar product
|
||||
@@ -94,13 +94,8 @@ _scalarmult :: proc(out, scalar, point: ^[32]byte) {
|
||||
field.fe_carry_mul(&x2, field.fe_relax_cast(&x2), field.fe_relax_cast(&z2))
|
||||
field.fe_to_bytes(out, &x2)
|
||||
|
||||
mem.zero_explicit(&x1, size_of(x1))
|
||||
mem.zero_explicit(&x2, size_of(x2))
|
||||
mem.zero_explicit(&x3, size_of(x3))
|
||||
mem.zero_explicit(&z2, size_of(z2))
|
||||
mem.zero_explicit(&z3, size_of(z3))
|
||||
mem.zero_explicit(&t0, size_of(t0))
|
||||
mem.zero_explicit(&t1, size_of(t1))
|
||||
field.fe_clear_vec([]^field.Tight_Field_Element{&x1, &x2, &x3, &z2, &z3})
|
||||
field.fe_clear_vec([]^field.Loose_Field_Element{&t0, &t1})
|
||||
}
|
||||
|
||||
// scalarmult "multiplies" the provided scalar and point, and writes the
|
||||
@@ -137,6 +132,5 @@ scalarmult :: proc(dst, scalar, point: []byte) {
|
||||
// scalarmult_basepoint "multiplies" the provided scalar with the X25519
|
||||
// base point and writes the resulting point to dst.
|
||||
scalarmult_basepoint :: proc(dst, scalar: []byte) {
|
||||
// TODO/perf: Switch to using a precomputed table.
|
||||
scalarmult(dst, scalar, _BASE_POINT[:])
|
||||
}
|
||||
|
||||
@@ -366,11 +366,63 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
|
||||
opt_write_end(w, opt, '}') or_return
|
||||
|
||||
case runtime.Type_Info_Struct:
|
||||
is_omitempty :: proc(v: any) -> bool {
|
||||
v := v
|
||||
if v == nil {
|
||||
return true
|
||||
}
|
||||
ti := runtime.type_info_core(type_info_of(v.id))
|
||||
#partial switch info in ti.variant {
|
||||
case runtime.Type_Info_String:
|
||||
switch x in v {
|
||||
case string:
|
||||
return x == ""
|
||||
case cstring:
|
||||
return x == nil || x == ""
|
||||
}
|
||||
case runtime.Type_Info_Any:
|
||||
return v.(any) == nil
|
||||
case runtime.Type_Info_Type_Id:
|
||||
return v.(typeid) == nil
|
||||
case runtime.Type_Info_Pointer,
|
||||
runtime.Type_Info_Multi_Pointer,
|
||||
runtime.Type_Info_Procedure:
|
||||
return (^rawptr)(v.data)^ == nil
|
||||
case runtime.Type_Info_Dynamic_Array:
|
||||
return (^runtime.Raw_Dynamic_Array)(v.data).len == 0
|
||||
case runtime.Type_Info_Slice:
|
||||
return (^runtime.Raw_Slice)(v.data).len == 0
|
||||
case runtime.Type_Info_Union,
|
||||
runtime.Type_Info_Bit_Set,
|
||||
runtime.Type_Info_Soa_Pointer:
|
||||
return reflect.is_nil(v)
|
||||
case runtime.Type_Info_Map:
|
||||
return (^runtime.Raw_Map)(v.data).len == 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
marshal_struct_fields :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: Marshal_Error) {
|
||||
ti := runtime.type_info_base(type_info_of(v.id))
|
||||
info := ti.variant.(runtime.Type_Info_Struct)
|
||||
for name, i in info.names {
|
||||
json_name := reflect.struct_tag_get(reflect.Struct_Tag(info.tags[i]), "json")
|
||||
omitempty := false
|
||||
|
||||
json_name, extra := json_name_from_tag_value(reflect.struct_tag_get(reflect.Struct_Tag(info.tags[i]), "json"))
|
||||
for flag in strings.split_iterator(&extra, ",") {
|
||||
switch flag {
|
||||
case "omitempty":
|
||||
omitempty = true
|
||||
}
|
||||
}
|
||||
|
||||
id := info.types[i].id
|
||||
data := rawptr(uintptr(v.data) + info.offsets[i])
|
||||
the_value := any{data, id}
|
||||
|
||||
if is_omitempty(the_value) {
|
||||
continue
|
||||
}
|
||||
|
||||
opt_write_iteration(w, opt, i) or_return
|
||||
if json_name != "" {
|
||||
@@ -378,18 +430,15 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
|
||||
} else {
|
||||
// Marshal the fields of 'using _: T' fields directly into the parent struct
|
||||
if info.usings[i] && name == "_" {
|
||||
id := info.types[i].id
|
||||
data := rawptr(uintptr(v.data) + info.offsets[i])
|
||||
marshal_struct_fields(w, any{data, id}, opt) or_return
|
||||
marshal_struct_fields(w, the_value, opt) or_return
|
||||
continue
|
||||
} else {
|
||||
opt_write_key(w, opt, name) or_return
|
||||
}
|
||||
}
|
||||
|
||||
id := info.types[i].id
|
||||
data := rawptr(uintptr(v.data) + info.offsets[i])
|
||||
marshal_to_writer(w, any{data, id}, opt) or_return
|
||||
|
||||
marshal_to_writer(w, the_value, opt) or_return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -343,6 +343,16 @@ unmarshal_expect_token :: proc(p: ^Parser, kind: Token_Kind, loc := #caller_loca
|
||||
return prev
|
||||
}
|
||||
|
||||
@(private)
|
||||
json_name_from_tag_value :: proc(value: string) -> (json_name, extra: string) {
|
||||
json_name = value
|
||||
if comma_index := strings.index_byte(json_name, ','); comma_index >= 0 {
|
||||
json_name = json_name[:comma_index]
|
||||
extra = json_name[comma_index:]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(private)
|
||||
unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unmarshal_Error) {
|
||||
@@ -384,7 +394,8 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
|
||||
|
||||
for field, field_idx in fields {
|
||||
tag_value := string(reflect.struct_tag_get(field.tag, "json"))
|
||||
if key == tag_value {
|
||||
json_name, _ := json_name_from_tag_value(tag_value)
|
||||
if key == json_name {
|
||||
use_field_idx = field_idx
|
||||
break
|
||||
}
|
||||
|
||||
+1
-1
@@ -2711,7 +2711,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
|
||||
}
|
||||
} else {
|
||||
io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n)
|
||||
io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n)
|
||||
defer io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n)
|
||||
for i in 0..<info.count {
|
||||
if i > 0 { io.write_string(fi.writer, ", ", &fi.n) }
|
||||
|
||||
|
||||
+168
-20
@@ -102,37 +102,51 @@ round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
|
||||
return (x.i + (1 << (Fraction_Width - 1))) >> Fraction_Width
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string {
|
||||
Integer_Width :: 8*size_of(Backing) - Fraction_Width
|
||||
|
||||
x := x
|
||||
buf: [48]byte
|
||||
i := 0
|
||||
if x.i < 0 {
|
||||
|
||||
if !intrinsics.type_is_unsigned(Backing) && x.i == min(Backing) {
|
||||
// edge case handling for signed numbers
|
||||
buf[i] = '-'
|
||||
i += 1
|
||||
x.i = -x.i
|
||||
}
|
||||
|
||||
integer := x.i >> Fraction_Width
|
||||
fraction := x.i & (1<<Fraction_Width - 1)
|
||||
|
||||
s := strconv.append_uint(buf[i:], u64(integer), 10)
|
||||
i += len(s)
|
||||
if fraction != 0 {
|
||||
buf[i] = '.'
|
||||
i += 1
|
||||
for fraction > 0 {
|
||||
fraction *= 10
|
||||
buf[i] = byte('0' + (fraction>>Fraction_Width))
|
||||
i += copy(buf[i:], _power_of_two_table[Integer_Width])
|
||||
} else {
|
||||
if x.i < 0 {
|
||||
buf[i] = '-'
|
||||
i += 1
|
||||
fraction &= 1<<Fraction_Width - 1
|
||||
x.i = -x.i
|
||||
}
|
||||
|
||||
when size_of(Backing) < 16 {
|
||||
T :: u64
|
||||
append_uint :: strconv.append_uint
|
||||
} else {
|
||||
T :: u128
|
||||
append_uint :: strconv.append_u128
|
||||
}
|
||||
|
||||
integer := T(x.i) >> Fraction_Width
|
||||
fraction := T(x.i) & (1<<Fraction_Width - 1)
|
||||
|
||||
s := append_uint(buf[i:], integer, 10)
|
||||
i += len(s)
|
||||
if fraction != 0 {
|
||||
buf[i] = '.'
|
||||
i += 1
|
||||
for fraction > 0 {
|
||||
fraction *= 10
|
||||
buf[i] = byte('0' + (fraction>>Fraction_Width) % 10)
|
||||
i += 1
|
||||
fraction &= 1<<Fraction_Width - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
n := copy(dst, buf[:i])
|
||||
return string(dst[:i])
|
||||
}
|
||||
@@ -146,3 +160,137 @@ to_string :: proc(x: $T/Fixed($Backing, $Fraction_Width), allocator := context.a
|
||||
copy(str, s)
|
||||
return string(str)
|
||||
}
|
||||
|
||||
|
||||
@(private)
|
||||
_power_of_two_table := [129]string{
|
||||
"0.5",
|
||||
"1",
|
||||
"2",
|
||||
"4",
|
||||
"8",
|
||||
"16",
|
||||
"32",
|
||||
"64",
|
||||
"128",
|
||||
"256",
|
||||
"512",
|
||||
"1024",
|
||||
"2048",
|
||||
"4096",
|
||||
"8192",
|
||||
"16384",
|
||||
"32768",
|
||||
"65536",
|
||||
"131072",
|
||||
"262144",
|
||||
"524288",
|
||||
"1048576",
|
||||
"2097152",
|
||||
"4194304",
|
||||
"8388608",
|
||||
"16777216",
|
||||
"33554432",
|
||||
"67108864",
|
||||
"134217728",
|
||||
"268435456",
|
||||
"536870912",
|
||||
"1073741824",
|
||||
"2147483648",
|
||||
"4294967296",
|
||||
"8589934592",
|
||||
"17179869184",
|
||||
"34359738368",
|
||||
"68719476736",
|
||||
"137438953472",
|
||||
"274877906944",
|
||||
"549755813888",
|
||||
"1099511627776",
|
||||
"2199023255552",
|
||||
"4398046511104",
|
||||
"8796093022208",
|
||||
"17592186044416",
|
||||
"35184372088832",
|
||||
"70368744177664",
|
||||
"140737488355328",
|
||||
"281474976710656",
|
||||
"562949953421312",
|
||||
"1125899906842624",
|
||||
"2251799813685248",
|
||||
"4503599627370496",
|
||||
"9007199254740992",
|
||||
"18014398509481984",
|
||||
"36028797018963968",
|
||||
"72057594037927936",
|
||||
"144115188075855872",
|
||||
"288230376151711744",
|
||||
"576460752303423488",
|
||||
"1152921504606846976",
|
||||
"2305843009213693952",
|
||||
"4611686018427387904",
|
||||
"9223372036854775808",
|
||||
"18446744073709551616",
|
||||
"36893488147419103232",
|
||||
"73786976294838206464",
|
||||
"147573952589676412928",
|
||||
"295147905179352825856",
|
||||
"590295810358705651712",
|
||||
"1180591620717411303424",
|
||||
"2361183241434822606848",
|
||||
"4722366482869645213696",
|
||||
"9444732965739290427392",
|
||||
"18889465931478580854784",
|
||||
"37778931862957161709568",
|
||||
"75557863725914323419136",
|
||||
"151115727451828646838272",
|
||||
"302231454903657293676544",
|
||||
"604462909807314587353088",
|
||||
"1208925819614629174706176",
|
||||
"2417851639229258349412352",
|
||||
"4835703278458516698824704",
|
||||
"9671406556917033397649408",
|
||||
"19342813113834066795298816",
|
||||
"38685626227668133590597632",
|
||||
"77371252455336267181195264",
|
||||
"154742504910672534362390528",
|
||||
"309485009821345068724781056",
|
||||
"618970019642690137449562112",
|
||||
"1237940039285380274899124224",
|
||||
"2475880078570760549798248448",
|
||||
"4951760157141521099596496896",
|
||||
"9903520314283042199192993792",
|
||||
"19807040628566084398385987584",
|
||||
"39614081257132168796771975168",
|
||||
"79228162514264337593543950336",
|
||||
"158456325028528675187087900672",
|
||||
"316912650057057350374175801344",
|
||||
"633825300114114700748351602688",
|
||||
"1267650600228229401496703205376",
|
||||
"2535301200456458802993406410752",
|
||||
"5070602400912917605986812821504",
|
||||
"10141204801825835211973625643008",
|
||||
"20282409603651670423947251286016",
|
||||
"40564819207303340847894502572032",
|
||||
"81129638414606681695789005144064",
|
||||
"162259276829213363391578010288128",
|
||||
"324518553658426726783156020576256",
|
||||
"649037107316853453566312041152512",
|
||||
"1298074214633706907132624082305024",
|
||||
"2596148429267413814265248164610048",
|
||||
"5192296858534827628530496329220096",
|
||||
"10384593717069655257060992658440192",
|
||||
"20769187434139310514121985316880384",
|
||||
"41538374868278621028243970633760768",
|
||||
"83076749736557242056487941267521536",
|
||||
"166153499473114484112975882535043072",
|
||||
"332306998946228968225951765070086144",
|
||||
"664613997892457936451903530140172288",
|
||||
"1329227995784915872903807060280344576",
|
||||
"2658455991569831745807614120560689152",
|
||||
"5316911983139663491615228241121378304",
|
||||
"10633823966279326983230456482242756608",
|
||||
"21267647932558653966460912964485513216",
|
||||
"42535295865117307932921825928971026432",
|
||||
"85070591730234615865843651857942052864",
|
||||
"170141183460469231731687303715884105728",
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ sqrt :: proc{
|
||||
@(require_results) sin_f32be :: proc "contextless" (θ: f32be) -> f32be { return #force_inline f32be(sin_f32(f32(θ))) }
|
||||
@(require_results) sin_f64le :: proc "contextless" (θ: f64le) -> f64le { return #force_inline f64le(sin_f64(f64(θ))) }
|
||||
@(require_results) sin_f64be :: proc "contextless" (θ: f64be) -> f64be { return #force_inline f64be(sin_f64(f64(θ))) }
|
||||
// Return the sine of θ in radians.
|
||||
sin :: proc{
|
||||
sin_f16, sin_f16le, sin_f16be,
|
||||
sin_f32, sin_f32le, sin_f32be,
|
||||
@@ -72,6 +73,7 @@ sin :: proc{
|
||||
@(require_results) cos_f32be :: proc "contextless" (θ: f32be) -> f32be { return #force_inline f32be(cos_f32(f32(θ))) }
|
||||
@(require_results) cos_f64le :: proc "contextless" (θ: f64le) -> f64le { return #force_inline f64le(cos_f64(f64(θ))) }
|
||||
@(require_results) cos_f64be :: proc "contextless" (θ: f64be) -> f64be { return #force_inline f64be(cos_f64(f64(θ))) }
|
||||
// Return the cosine of θ in radians.
|
||||
cos :: proc{
|
||||
cos_f16, cos_f16le, cos_f16be,
|
||||
cos_f32, cos_f32le, cos_f32be,
|
||||
@@ -378,6 +380,7 @@ log10 :: proc{
|
||||
@(require_results) tan_f64 :: proc "contextless" (θ: f64) -> f64 { return sin(θ)/cos(θ) }
|
||||
@(require_results) tan_f64le :: proc "contextless" (θ: f64le) -> f64le { return f64le(tan_f64(f64(θ))) }
|
||||
@(require_results) tan_f64be :: proc "contextless" (θ: f64be) -> f64be { return f64be(tan_f64(f64(θ))) }
|
||||
// Return the tangent of θ in radians.
|
||||
tan :: proc{
|
||||
tan_f16, tan_f16le, tan_f16be,
|
||||
tan_f32, tan_f32le, tan_f32be,
|
||||
@@ -1752,7 +1755,28 @@ atan2_f64be :: proc "contextless" (y, x: f64be) -> f64be {
|
||||
// TODO(bill): Better atan2_f32
|
||||
return f64be(atan2_f64(f64(y), f64(x)))
|
||||
}
|
||||
/*
|
||||
Return the arc tangent of y/x in radians. Defined on the domain [-∞, ∞] for x and y with a range of [-π, π]
|
||||
|
||||
Special cases:
|
||||
atan2(y, NaN) = NaN
|
||||
atan2(NaN, x) = NaN
|
||||
atan2(+0, x>=0) = + 0
|
||||
atan2(-0, x>=0) = - 0
|
||||
atan2(+0, x<=-0) = + π
|
||||
atan2(-0, x<=-0) = - π
|
||||
atan2(y>0, 0) = + π/2
|
||||
atan2(y<0, 0) = - π/2
|
||||
atan2(+∞, +∞) = + π/4
|
||||
atan2(-∞, +∞) = - π/4
|
||||
atan2(+∞, -∞) = 3π/4
|
||||
atan2(-∞, -∞) = - 3π/4
|
||||
atan2(y, +∞) = 0
|
||||
atan2(y>0, -∞) = + π
|
||||
atan2(y<0, -∞) = - π
|
||||
atan2(+∞, x) = + π/2
|
||||
atan2(-∞, x) = - π/2
|
||||
*/
|
||||
atan2 :: proc{
|
||||
atan2_f64, atan2_f32, atan2_f16,
|
||||
atan2_f64le, atan2_f64be,
|
||||
@@ -1760,6 +1784,7 @@ atan2 :: proc{
|
||||
atan2_f16le, atan2_f16be,
|
||||
}
|
||||
|
||||
// Return the arc tangent of x, in radians. Defined on the domain of [-∞, ∞] with a range of [-π/2, π/2]
|
||||
@(require_results)
|
||||
atan :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) {
|
||||
return atan2(x, 1)
|
||||
@@ -1871,6 +1896,7 @@ asin_f16le :: proc "contextless" (x: f16le) -> f16le {
|
||||
asin_f16be :: proc "contextless" (x: f16be) -> f16be {
|
||||
return f16be(asin_f64(f64(x)))
|
||||
}
|
||||
// Return the arc sine of x, in radians. Defined on the domain of [-1, 1] with a range of [-π/2, π/2]
|
||||
asin :: proc{
|
||||
asin_f64, asin_f32, asin_f16,
|
||||
asin_f64le, asin_f64be,
|
||||
@@ -1985,6 +2011,7 @@ acos_f16le :: proc "contextless" (x: f16le) -> f16le {
|
||||
acos_f16be :: proc "contextless" (x: f16be) -> f16be {
|
||||
return f16be(acos_f64(f64(x)))
|
||||
}
|
||||
// Return the arc cosine of x, in radians. Defined on the domain of [-1, 1] with a range of [0, π].
|
||||
acos :: proc{
|
||||
acos_f64, acos_f32, acos_f16,
|
||||
acos_f64le, acos_f64be,
|
||||
|
||||
+15
-2
@@ -21,7 +21,7 @@ import "core:strconv"
|
||||
import "core:unicode/utf8"
|
||||
import "core:encoding/hex"
|
||||
|
||||
split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, path: string, queries: map[string]string) {
|
||||
split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, path: string, queries: map[string]string, fragment: string) {
|
||||
s := url
|
||||
|
||||
i := strings.index(s, "://")
|
||||
@@ -30,6 +30,12 @@ split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host,
|
||||
s = s[i+3:]
|
||||
}
|
||||
|
||||
i = strings.index(s, "#")
|
||||
if i != -1 {
|
||||
fragment = s[i+1:]
|
||||
s = s[:i]
|
||||
}
|
||||
|
||||
i = strings.index(s, "?")
|
||||
if i != -1 {
|
||||
query_str := s[i+1:]
|
||||
@@ -62,7 +68,7 @@ split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host,
|
||||
return
|
||||
}
|
||||
|
||||
join_url :: proc(scheme, host, path: string, queries: map[string]string, allocator := context.allocator) -> string {
|
||||
join_url :: proc(scheme, host, path: string, queries: map[string]string, fragment: string, allocator := context.allocator) -> string {
|
||||
b := strings.builder_make(allocator)
|
||||
strings.builder_grow(&b, len(scheme) + 3 + len(host) + 1 + len(path))
|
||||
|
||||
@@ -95,6 +101,13 @@ join_url :: proc(scheme, host, path: string, queries: map[string]string, allocat
|
||||
i += 1
|
||||
}
|
||||
|
||||
if fragment != "" {
|
||||
if fragment[0] != '#' {
|
||||
strings.write_string(&b, "#")
|
||||
}
|
||||
strings.write_string(&b, strings.trim_space(fragment))
|
||||
}
|
||||
|
||||
return strings.to_string(b)
|
||||
}
|
||||
|
||||
|
||||
+21
-1
@@ -617,7 +617,7 @@ field_flag_strings := [Field_Flag]string{
|
||||
.Any_Int = "#any_int",
|
||||
.Subtype = "#subtype",
|
||||
.By_Ptr = "#by_ptr",
|
||||
.No_Broadcast ="#no_broadcast",
|
||||
.No_Broadcast = "#no_broadcast",
|
||||
|
||||
.Results = "results",
|
||||
.Tags = "field tag",
|
||||
@@ -842,6 +842,23 @@ Matrix_Type :: struct {
|
||||
elem: ^Expr,
|
||||
}
|
||||
|
||||
Bit_Field_Type :: struct {
|
||||
using node: Expr,
|
||||
tok_pos: tokenizer.Pos,
|
||||
backing_type: ^Expr,
|
||||
open: tokenizer.Pos,
|
||||
fields: []^Bit_Field_Field,
|
||||
close: tokenizer.Pos,
|
||||
}
|
||||
|
||||
Bit_Field_Field :: struct {
|
||||
using node: Node,
|
||||
docs: ^Comment_Group,
|
||||
name: ^Expr,
|
||||
type: ^Expr,
|
||||
bit_size: ^Expr,
|
||||
comments: ^Comment_Group,
|
||||
}
|
||||
|
||||
Any_Node :: union {
|
||||
^Package,
|
||||
@@ -898,6 +915,7 @@ Any_Node :: union {
|
||||
^Map_Type,
|
||||
^Relative_Type,
|
||||
^Matrix_Type,
|
||||
^Bit_Field_Type,
|
||||
|
||||
^Bad_Stmt,
|
||||
^Empty_Stmt,
|
||||
@@ -928,6 +946,7 @@ Any_Node :: union {
|
||||
^Attribute,
|
||||
^Field,
|
||||
^Field_List,
|
||||
^Bit_Field_Field,
|
||||
}
|
||||
|
||||
|
||||
@@ -982,6 +1001,7 @@ Any_Expr :: union {
|
||||
^Map_Type,
|
||||
^Relative_Type,
|
||||
^Matrix_Type,
|
||||
^Bit_Field_Type,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -336,6 +336,13 @@ clone_node :: proc(node: ^Node) -> ^Node {
|
||||
case ^Relative_Type:
|
||||
r.tag = clone(r.tag)
|
||||
r.type = clone(r.type)
|
||||
case ^Bit_Field_Type:
|
||||
r.backing_type = clone(r.backing_type)
|
||||
r.fields = auto_cast clone(r.fields)
|
||||
case ^Bit_Field_Field:
|
||||
r.name = clone(r.name)
|
||||
r.type = clone(r.type)
|
||||
r.bit_size = clone(r.bit_size)
|
||||
case:
|
||||
fmt.panicf("Unhandled node kind: %v", r)
|
||||
}
|
||||
|
||||
@@ -414,7 +414,15 @@ walk :: proc(v: ^Visitor, node: ^Node) {
|
||||
walk(v, n.row_count)
|
||||
walk(v, n.column_count)
|
||||
walk(v, n.elem)
|
||||
|
||||
case ^Bit_Field_Type:
|
||||
walk(v, n.backing_type)
|
||||
for f in n.fields {
|
||||
walk(v, f)
|
||||
}
|
||||
case ^Bit_Field_Field:
|
||||
walk(v, n.name)
|
||||
walk(v, n.type)
|
||||
walk(v, n.bit_size)
|
||||
case:
|
||||
fmt.panicf("ast.walk: unexpected node type %T", n)
|
||||
}
|
||||
|
||||
@@ -416,24 +416,28 @@ end_of_line_pos :: proc(p: ^Parser, tok: tokenizer.Token) -> tokenizer.Pos {
|
||||
}
|
||||
|
||||
expect_closing_brace_of_field_list :: proc(p: ^Parser) -> tokenizer.Token {
|
||||
return expect_closing_token_of_field_list(p, .Close_Brace, "field list")
|
||||
}
|
||||
|
||||
expect_closing_token_of_field_list :: proc(p: ^Parser, closing_kind: tokenizer.Token_Kind, msg: string) -> tokenizer.Token {
|
||||
token := p.curr_tok
|
||||
if allow_token(p, .Close_Brace) {
|
||||
if allow_token(p, closing_kind) {
|
||||
return token
|
||||
}
|
||||
if allow_token(p, .Semicolon) && !tokenizer.is_newline(token) {
|
||||
str := tokenizer.token_to_string(token)
|
||||
error(p, end_of_line_pos(p, p.prev_tok), "expected a comma, got %s", str)
|
||||
}
|
||||
expect_brace := expect_token(p, .Close_Brace)
|
||||
expect_closing := expect_token_after(p, closing_kind, msg)
|
||||
|
||||
if expect_brace.kind != .Close_Brace {
|
||||
for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF && !is_non_inserted_semicolon(p.curr_tok) {
|
||||
if expect_closing.kind != closing_kind {
|
||||
for p.curr_tok.kind != closing_kind && p.curr_tok.kind != .EOF && !is_non_inserted_semicolon(p.curr_tok) {
|
||||
advance_token(p)
|
||||
}
|
||||
return p.curr_tok
|
||||
}
|
||||
|
||||
return expect_brace
|
||||
return expect_closing
|
||||
}
|
||||
|
||||
expect_closing_parentheses_of_field_list :: proc(p: ^Parser) -> tokenizer.Token {
|
||||
@@ -531,7 +535,7 @@ is_semicolon_optional_for_node :: proc(p: ^Parser, node: ^ast.Node) -> bool {
|
||||
return is_semicolon_optional_for_node(p, n.type)
|
||||
case ^ast.Pointer_Type:
|
||||
return is_semicolon_optional_for_node(p, n.elem)
|
||||
case ^ast.Struct_Type, ^ast.Union_Type, ^ast.Enum_Type:
|
||||
case ^ast.Struct_Type, ^ast.Union_Type, ^ast.Enum_Type, ^ast.Bit_Set_Type, ^ast.Bit_Field_Type:
|
||||
// Require semicolon within a procedure body
|
||||
return p.curr_proc == nil
|
||||
case ^ast.Proc_Lit:
|
||||
@@ -1354,6 +1358,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
|
||||
rs := ast.new(ast.Return_Stmt, tok.pos, end)
|
||||
rs.results = results[:]
|
||||
expect_semicolon(p, rs)
|
||||
return rs
|
||||
|
||||
case .Break, .Continue, .Fallthrough:
|
||||
@@ -2790,6 +2795,48 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
mt.column_count = column_count
|
||||
mt.elem = elem
|
||||
return mt
|
||||
|
||||
case .Bit_Field:
|
||||
tok := expect_token(p, .Bit_Field)
|
||||
|
||||
backing_type := parse_type_or_ident(p)
|
||||
if backing_type == nil {
|
||||
token := advance_token(p)
|
||||
error(p, token.pos, "Expected a backing type for a 'bit_field'")
|
||||
}
|
||||
|
||||
skip_possible_newline_for_literal(p)
|
||||
open := expect_token_after(p, .Open_Brace, "bit_field")
|
||||
|
||||
fields: [dynamic]^ast.Bit_Field_Field
|
||||
for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF {
|
||||
name := parse_ident(p)
|
||||
expect_token(p, .Colon)
|
||||
type := parse_type(p)
|
||||
expect_token(p, .Or)
|
||||
bit_size := parse_expr(p, true)
|
||||
|
||||
field := ast.new(ast.Bit_Field_Field, name.pos, bit_size)
|
||||
|
||||
field.name = name
|
||||
field.type = type
|
||||
field.bit_size = bit_size
|
||||
|
||||
append(&fields, field)
|
||||
|
||||
allow_token(p, .Comma) or_break
|
||||
}
|
||||
|
||||
close := expect_closing_brace_of_field_list(p)
|
||||
|
||||
bf := ast.new(ast.Bit_Field_Type, tok.pos, close.pos)
|
||||
|
||||
bf.tok_pos = tok.pos
|
||||
bf.backing_type = backing_type
|
||||
bf.open = open.pos
|
||||
bf.fields = fields[:]
|
||||
bf.close = close.pos
|
||||
return bf
|
||||
|
||||
case .Asm:
|
||||
tok := expect_token(p, .Asm)
|
||||
@@ -2897,7 +2944,8 @@ is_literal_type :: proc(expr: ^ast.Expr) -> bool {
|
||||
^ast.Map_Type,
|
||||
^ast.Bit_Set_Type,
|
||||
^ast.Matrix_Type,
|
||||
^ast.Call_Expr:
|
||||
^ast.Call_Expr,
|
||||
^ast.Bit_Field_Type:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -2947,8 +2995,8 @@ parse_literal_value :: proc(p: ^Parser, type: ^ast.Expr) -> ^ast.Comp_Lit {
|
||||
}
|
||||
p.expr_level -= 1
|
||||
|
||||
skip_possible_newline(p)
|
||||
close := expect_token_after(p, .Close_Brace, "compound literal")
|
||||
skip_possible_newline(p)
|
||||
close := expect_closing_brace_of_field_list(p)
|
||||
|
||||
pos := type.pos if type != nil else open.pos
|
||||
lit := ast.new(ast.Comp_Lit, pos, end_pos(close))
|
||||
@@ -3011,7 +3059,7 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr {
|
||||
allow_token(p, .Comma) or_break
|
||||
}
|
||||
|
||||
close := expect_token_after(p, .Close_Paren, "argument list")
|
||||
close := expect_closing_token_of_field_list(p, .Close_Paren, "argument list")
|
||||
p.expr_level -= 1
|
||||
|
||||
ce := ast.new(ast.Call_Expr, operand.pos, end_pos(close))
|
||||
|
||||
@@ -445,7 +445,7 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) {
|
||||
|
||||
for value in v.values {
|
||||
#partial switch a in value.derived {
|
||||
case ^ast.Union_Type, ^ast.Enum_Type, ^ast.Struct_Type:
|
||||
case ^ast.Union_Type, ^ast.Enum_Type, ^ast.Struct_Type, ^ast.Bit_Field_Type:
|
||||
add_semicolon = false || called_in_stmt
|
||||
case ^ast.Proc_Lit:
|
||||
add_semicolon = false
|
||||
@@ -488,6 +488,37 @@ visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, options := List_Options{}) {
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
visit_bit_field_fields :: proc(p: ^Printer, list: []^ast.Bit_Field_Field, options := List_Options{}) {
|
||||
if len(list) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// we have to newline the expressions to respect the source
|
||||
for v, i in list {
|
||||
// Don't move the first expression, it looks bad
|
||||
if i != 0 && .Enforce_Newline in options {
|
||||
newline_position(p, 1)
|
||||
} else if i != 0 {
|
||||
move_line_limit(p, v.pos, 1)
|
||||
}
|
||||
|
||||
visit_expr(p, v.name, options)
|
||||
push_generic_token(p, .Colon, 0)
|
||||
visit_expr(p, v.type, options)
|
||||
push_generic_token(p, .Or, 1)
|
||||
visit_expr(p, v.bit_size, options)
|
||||
|
||||
if (i != len(list) - 1 || .Trailing in options) && .Add_Comma in options {
|
||||
push_generic_token(p, .Comma, 0)
|
||||
}
|
||||
}
|
||||
|
||||
if len(list) > 1 && .Enforce_Newline in options {
|
||||
newline_position(p, 1)
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) {
|
||||
if len(attributes) == 0 {
|
||||
@@ -1293,6 +1324,25 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, options := List_Options{}) {
|
||||
visit_expr(p, v.column_count)
|
||||
push_generic_token(p, .Close_Bracket, 0)
|
||||
visit_expr(p, v.elem)
|
||||
case ^ast.Bit_Field_Type:
|
||||
push_generic_token(p, .Bit_Field, 1)
|
||||
|
||||
visit_expr(p, v.backing_type)
|
||||
|
||||
if len(v.fields) == 0 || v.pos.line == v.close.line {
|
||||
push_generic_token(p, .Open_Brace, 1)
|
||||
visit_bit_field_fields(p, v.fields, {.Add_Comma})
|
||||
push_generic_token(p, .Close_Brace, 0)
|
||||
} else {
|
||||
visit_begin_brace(p, v.pos, .Generic, len(v.fields))
|
||||
newline_position(p, 1)
|
||||
set_source_position(p, v.fields[0].pos)
|
||||
visit_bit_field_fields(p, v.fields, {.Add_Comma, .Trailing, .Enforce_Newline})
|
||||
set_source_position(p, v.close)
|
||||
visit_end_brace(p, v.close)
|
||||
}
|
||||
|
||||
set_source_position(p, v.close)
|
||||
case:
|
||||
panic(fmt.aprint(expr.derived))
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ init :: proc(t: ^Tokenizer, src: string, path: string, err: Error_Handler = defa
|
||||
t.read_offset = 0
|
||||
t.line_offset = 0
|
||||
t.line_count = len(src) > 0 ? 1 : 0
|
||||
t.insert_semicolon = false
|
||||
t.error_count = 0
|
||||
t.path = path
|
||||
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ package os
|
||||
import "core:time"
|
||||
|
||||
File_Info :: struct {
|
||||
fullpath: string,
|
||||
name: string,
|
||||
fullpath: string, // allocated
|
||||
name: string, // uses `fullpath` as underlying data
|
||||
size: i64,
|
||||
mode: File_Mode,
|
||||
is_dir: bool,
|
||||
|
||||
@@ -1213,6 +1213,13 @@ Output:
|
||||
append_int :: proc(buf: []byte, i: i64, base: int) -> string {
|
||||
return append_bits(buf, u64(i), base, true, 8*size_of(int), digits, nil)
|
||||
}
|
||||
|
||||
|
||||
|
||||
append_u128 :: proc(buf: []byte, u: u128, base: int) -> string {
|
||||
return append_bits_128(buf, u, base, false, 8*size_of(uint), digits, nil)
|
||||
}
|
||||
|
||||
/*
|
||||
Converts an integer value to a string and stores it in the given buffer
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package sync
|
||||
|
||||
import "core:c"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:sys/haiku"
|
||||
import "core:sys/unix"
|
||||
import "core:time"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package CoreFoundation
|
||||
|
||||
foreign import CoreFoundation "system:CoreFoundation.framework"
|
||||
|
||||
TypeID :: distinct uint
|
||||
OptionFlags :: distinct uint
|
||||
HashCode :: distinct uint
|
||||
Index :: distinct int
|
||||
TypeRef :: distinct rawptr
|
||||
|
||||
Range :: struct {
|
||||
location: Index,
|
||||
length: Index,
|
||||
}
|
||||
|
||||
foreign CoreFoundation {
|
||||
// Releases a Core Foundation object.
|
||||
CFRelease :: proc(cf: TypeRef) ---
|
||||
}
|
||||
|
||||
// Releases a Core Foundation object.
|
||||
Release :: proc {
|
||||
ReleaseObject,
|
||||
ReleaseString,
|
||||
}
|
||||
|
||||
ReleaseObject :: #force_inline proc(cf: TypeRef) {
|
||||
CFRelease(cf)
|
||||
}
|
||||
|
||||
// Releases a Core Foundation string.
|
||||
ReleaseString :: #force_inline proc(theString: String) {
|
||||
CFRelease(TypeRef(theString))
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package CoreFoundation
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
foreign import CoreFoundation "system:CoreFoundation.framework"
|
||||
|
||||
String :: distinct TypeRef // same as CFStringRef
|
||||
|
||||
StringEncoding :: distinct u32
|
||||
|
||||
StringBuiltInEncodings :: enum StringEncoding {
|
||||
MacRoman = 0,
|
||||
WindowsLatin1 = 0x0500,
|
||||
ISOLatin1 = 0x0201,
|
||||
NextStepLatin = 0x0B01,
|
||||
ASCII = 0x0600,
|
||||
Unicode = 0x0100,
|
||||
UTF8 = 0x08000100,
|
||||
NonLossyASCII = 0x0BFF,
|
||||
|
||||
UTF16 = 0x0100,
|
||||
UTF16BE = 0x10000100,
|
||||
UTF16LE = 0x14000100,
|
||||
|
||||
UTF32 = 0x0c000100,
|
||||
UTF32BE = 0x18000100,
|
||||
UTF32LE = 0x1c000100,
|
||||
}
|
||||
|
||||
StringEncodings :: enum Index {
|
||||
MacJapanese = 1,
|
||||
MacChineseTrad = 2,
|
||||
MacKorean = 3,
|
||||
MacArabic = 4,
|
||||
MacHebrew = 5,
|
||||
MacGreek = 6,
|
||||
MacCyrillic = 7,
|
||||
MacDevanagari = 9,
|
||||
MacGurmukhi = 10,
|
||||
MacGujarati = 11,
|
||||
MacOriya = 12,
|
||||
MacBengali = 13,
|
||||
MacTamil = 14,
|
||||
MacTelugu = 15,
|
||||
MacKannada = 16,
|
||||
MacMalayalam = 17,
|
||||
MacSinhalese = 18,
|
||||
MacBurmese = 19,
|
||||
MacKhmer = 20,
|
||||
MacThai = 21,
|
||||
MacLaotian = 22,
|
||||
MacGeorgian = 23,
|
||||
MacArmenian = 24,
|
||||
MacChineseSimp = 25,
|
||||
MacTibetan = 26,
|
||||
MacMongolian = 27,
|
||||
MacEthiopic = 28,
|
||||
MacCentralEurRoman = 29,
|
||||
MacVietnamese = 30,
|
||||
MacExtArabic = 31,
|
||||
MacSymbol = 33,
|
||||
MacDingbats = 34,
|
||||
MacTurkish = 35,
|
||||
MacCroatian = 36,
|
||||
MacIcelandic = 37,
|
||||
MacRomanian = 38,
|
||||
MacCeltic = 39,
|
||||
MacGaelic = 40,
|
||||
MacFarsi = 0x8C,
|
||||
MacUkrainian = 0x98,
|
||||
MacInuit = 0xEC,
|
||||
MacVT100 = 0xFC,
|
||||
MacHFS = 0xFF,
|
||||
ISOLatin2 = 0x0202,
|
||||
ISOLatin3 = 0x0203,
|
||||
ISOLatin4 = 0x0204,
|
||||
ISOLatinCyrillic = 0x0205,
|
||||
ISOLatinArabic = 0x0206,
|
||||
ISOLatinGreek = 0x0207,
|
||||
ISOLatinHebrew = 0x0208,
|
||||
ISOLatin5 = 0x0209,
|
||||
ISOLatin6 = 0x020A,
|
||||
ISOLatinThai = 0x020B,
|
||||
ISOLatin7 = 0x020D,
|
||||
ISOLatin8 = 0x020E,
|
||||
ISOLatin9 = 0x020F,
|
||||
ISOLatin10 = 0x0210,
|
||||
DOSLatinUS = 0x0400,
|
||||
DOSGreek = 0x0405,
|
||||
DOSBalticRim = 0x0406,
|
||||
DOSLatin1 = 0x0410,
|
||||
DOSGreek1 = 0x0411,
|
||||
DOSLatin2 = 0x0412,
|
||||
DOSCyrillic = 0x0413,
|
||||
DOSTurkish = 0x0414,
|
||||
DOSPortuguese = 0x0415,
|
||||
DOSIcelandic = 0x0416,
|
||||
DOSHebrew = 0x0417,
|
||||
DOSCanadianFrench = 0x0418,
|
||||
DOSArabic = 0x0419,
|
||||
DOSNordic = 0x041A,
|
||||
DOSRussian = 0x041B,
|
||||
DOSGreek2 = 0x041C,
|
||||
DOSThai = 0x041D,
|
||||
DOSJapanese = 0x0420,
|
||||
DOSChineseSimplif = 0x0421,
|
||||
DOSKorean = 0x0422,
|
||||
DOSChineseTrad = 0x0423,
|
||||
WindowsLatin2 = 0x0501,
|
||||
WindowsCyrillic = 0x0502,
|
||||
WindowsGreek = 0x0503,
|
||||
WindowsLatin5 = 0x0504,
|
||||
WindowsHebrew = 0x0505,
|
||||
WindowsArabic = 0x0506,
|
||||
WindowsBalticRim = 0x0507,
|
||||
WindowsVietnamese = 0x0508,
|
||||
WindowsKoreanJohab = 0x0510,
|
||||
ANSEL = 0x0601,
|
||||
JIS_X0201_76 = 0x0620,
|
||||
JIS_X0208_83 = 0x0621,
|
||||
JIS_X0208_90 = 0x0622,
|
||||
JIS_X0212_90 = 0x0623,
|
||||
JIS_C6226_78 = 0x0624,
|
||||
ShiftJIS_X0213 = 0x0628,
|
||||
ShiftJIS_X0213_MenKuTen = 0x0629,
|
||||
GB_2312_80 = 0x0630,
|
||||
GBK_95 = 0x0631,
|
||||
GB_18030_2000 = 0x0632,
|
||||
KSC_5601_87 = 0x0640,
|
||||
KSC_5601_92_Johab = 0x0641,
|
||||
CNS_11643_92_P1 = 0x0651,
|
||||
CNS_11643_92_P2 = 0x0652,
|
||||
CNS_11643_92_P3 = 0x0653,
|
||||
ISO_2022_JP = 0x0820,
|
||||
ISO_2022_JP_2 = 0x0821,
|
||||
ISO_2022_JP_1 = 0x0822,
|
||||
ISO_2022_JP_3 = 0x0823,
|
||||
ISO_2022_CN = 0x0830,
|
||||
ISO_2022_CN_EXT = 0x0831,
|
||||
ISO_2022_KR = 0x0840,
|
||||
EUC_JP = 0x0920,
|
||||
EUC_CN = 0x0930,
|
||||
EUC_TW = 0x0931,
|
||||
EUC_KR = 0x0940,
|
||||
ShiftJIS = 0x0A01,
|
||||
KOI8_R = 0x0A02,
|
||||
Big5 = 0x0A03,
|
||||
MacRomanLatin1 = 0x0A04,
|
||||
HZ_GB_2312 = 0x0A05,
|
||||
Big5_HKSCS_1999 = 0x0A06,
|
||||
VISCII = 0x0A07,
|
||||
KOI8_U = 0x0A08,
|
||||
Big5_E = 0x0A09,
|
||||
NextStepJapanese = 0x0B02,
|
||||
EBCDIC_US = 0x0C01,
|
||||
EBCDIC_CP037 = 0x0C02,
|
||||
UTF7 = 0x04000100,
|
||||
UTF7_IMAP = 0x0A10,
|
||||
ShiftJIS_X0213_00 = 0x0628, // Deprecated. Use `ShiftJIS_X0213` instead.
|
||||
}
|
||||
|
||||
@(link_prefix = "CF", default_calling_convention = "c")
|
||||
foreign CoreFoundation {
|
||||
// Copies the character contents of a string to a local C string buffer after converting the characters to a given encoding.
|
||||
StringGetCString :: proc(theString: String, buffer: [^]byte, bufferSize: Index, encoding: StringEncoding) -> b8 ---
|
||||
|
||||
// Returns the number (in terms of UTF-16 code pairs) of Unicode characters in a string.
|
||||
StringGetLength :: proc(theString: String) -> Index ---
|
||||
|
||||
// Returns the maximum number of bytes a string of a specified length (in Unicode characters) will take up if encoded in a specified encoding.
|
||||
StringGetMaximumSizeForEncoding :: proc(length: Index, encoding: StringEncoding) -> Index ---
|
||||
|
||||
// Fetches a range of the characters from a string into a byte buffer after converting the characters to a specified encoding.
|
||||
StringGetBytes :: proc(thestring: String, range: Range, encoding: StringEncoding, lossByte: u8, isExternalRepresentation: b8, buffer: [^]byte, maxBufLen: Index, usedBufLen: ^Index) -> Index ---
|
||||
|
||||
StringIsEncodingAvailable :: proc(encoding: StringEncoding) -> bool ---
|
||||
|
||||
@(link_name = "__CFStringMakeConstantString")
|
||||
StringMakeConstantString :: proc "c" (#const c: cstring) -> String ---
|
||||
}
|
||||
|
||||
STR :: StringMakeConstantString
|
||||
|
||||
StringCopyToOdinString :: proc(
|
||||
theString: String,
|
||||
allocator := context.allocator,
|
||||
) -> (
|
||||
str: string,
|
||||
ok: bool,
|
||||
) #optional_ok {
|
||||
length := StringGetLength(theString)
|
||||
max := StringGetMaximumSizeForEncoding(length, StringEncoding(StringBuiltInEncodings.UTF8))
|
||||
|
||||
buf, err := make([]byte, max, allocator)
|
||||
if err != nil do return
|
||||
|
||||
raw_str := runtime.Raw_String {
|
||||
data = raw_data(buf),
|
||||
}
|
||||
StringGetBytes(theString, {0, length}, StringEncoding(StringBuiltInEncodings.UTF8), 0, false, raw_data(buf), max, (^Index)(&raw_str.len))
|
||||
|
||||
return transmute(string)raw_str, true
|
||||
}
|
||||
@@ -0,0 +1,609 @@
|
||||
package objc_Foundation
|
||||
|
||||
foreign import "system:Foundation.framework"
|
||||
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
import "core:strings"
|
||||
|
||||
RunLoopMode :: ^String
|
||||
|
||||
@(link_prefix="NS")
|
||||
foreign Foundation {
|
||||
RunLoopCommonModes: RunLoopMode
|
||||
DefaultRunLoopMode: RunLoopMode
|
||||
EventTrackingRunLoopMode: RunLoopMode
|
||||
ModalPanelRunLoopMode: RunLoopMode
|
||||
}
|
||||
|
||||
ActivationPolicy :: enum UInteger {
|
||||
Regular = 0,
|
||||
Accessory = 1,
|
||||
Prohibited = 2,
|
||||
}
|
||||
|
||||
ApplicationTerminateReply :: enum UInteger {
|
||||
TerminateCancel = 0,
|
||||
TerminateNow = 1,
|
||||
TerminateLater = 2,
|
||||
}
|
||||
|
||||
ApplicationPrintReply :: enum UInteger {
|
||||
PrintingCancelled = 0,
|
||||
PrintingSuccess = 1,
|
||||
PrintingReplyLater = 2,
|
||||
PrintingFailure = 3,
|
||||
}
|
||||
|
||||
ApplicationPresentationOptionFlag :: enum UInteger {
|
||||
AutoHideDock = 0,
|
||||
HideDock = 1,
|
||||
AutoHideMenuBar = 2,
|
||||
HideMenuBar = 3,
|
||||
DisableAppleMenu = 4,
|
||||
DisableProcessSwitching = 5,
|
||||
DisableForceQuit = 6,
|
||||
DisableSessionTermination = 7,
|
||||
DisableHideApplication = 8,
|
||||
DisableMenuBarTransparency = 9,
|
||||
FullScreen = 10,
|
||||
AutoHideToolbar = 11,
|
||||
DisableCursorLocationAssistance = 12,
|
||||
}
|
||||
ApplicationPresentationOptions :: distinct bit_set[ApplicationPresentationOptionFlag; UInteger]
|
||||
ApplicationPresentationOptionsDefault :: ApplicationPresentationOptions {}
|
||||
ApplicationPresentationOptionsAutoHideDock :: ApplicationPresentationOptions {.AutoHideDock}
|
||||
ApplicationPresentationOptionsHideDock :: ApplicationPresentationOptions {.HideDock}
|
||||
ApplicationPresentationOptionsAutoHideMenuBar :: ApplicationPresentationOptions {.AutoHideMenuBar}
|
||||
ApplicationPresentationOptionsHideMenuBar :: ApplicationPresentationOptions {.HideMenuBar}
|
||||
ApplicationPresentationOptionsDisableAppleMenu :: ApplicationPresentationOptions {.DisableAppleMenu}
|
||||
ApplicationPresentationOptionsDisableProcessSwitching :: ApplicationPresentationOptions {.DisableProcessSwitching}
|
||||
ApplicationPresentationOptionsDisableForceQuit :: ApplicationPresentationOptions {.DisableForceQuit}
|
||||
ApplicationPresentationOptionsDisableSessionTermination :: ApplicationPresentationOptions {.DisableSessionTermination}
|
||||
ApplicationPresentationOptionsDisableHideApplication :: ApplicationPresentationOptions {.DisableHideApplication}
|
||||
ApplicationPresentationOptionsDisableMenuBarTransparency :: ApplicationPresentationOptions {.DisableMenuBarTransparency}
|
||||
ApplicationPresentationOptionsFullScreen :: ApplicationPresentationOptions {.FullScreen}
|
||||
ApplicationPresentationOptionsAutoHideToolbar :: ApplicationPresentationOptions {.AutoHideToolbar}
|
||||
ApplicationPresentationOptionsDisableCursorLocationAssistance :: ApplicationPresentationOptions {.DisableCursorLocationAssistance}
|
||||
|
||||
@(objc_class="NSApplication")
|
||||
Application :: struct {using _: Object}
|
||||
|
||||
@(objc_type=Application, objc_name="sharedApplication", objc_is_class_method=true)
|
||||
Application_sharedApplication :: proc "c" () -> ^Application {
|
||||
return msgSend(^Application, Application, "sharedApplication")
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="setActivationPolicy")
|
||||
Application_setActivationPolicy :: proc "c" (self: ^Application, activationPolicy: ActivationPolicy) -> BOOL {
|
||||
return msgSend(BOOL, self, "setActivationPolicy:", activationPolicy)
|
||||
}
|
||||
|
||||
@(deprecated="Use NSApplication method activate instead.")
|
||||
@(objc_type=Application, objc_name="activateIgnoringOtherApps")
|
||||
Application_activateIgnoringOtherApps :: proc "c" (self: ^Application, ignoreOtherApps: BOOL) {
|
||||
msgSend(nil, self, "activateIgnoringOtherApps:", ignoreOtherApps)
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="activate")
|
||||
Application_activate :: proc "c" (self: ^Application) {
|
||||
msgSend(nil, self, "activate")
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="setTitle")
|
||||
Application_setTitle :: proc "c" (self: ^Application, title: ^String) {
|
||||
msgSend(nil, self, "setTitle", title)
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="setMainMenu")
|
||||
Application_setMainMenu :: proc "c" (self: ^Application, menu: ^Menu) {
|
||||
msgSend(nil, self, "setMainMenu:", menu)
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="windows")
|
||||
Application_windows :: proc "c" (self: ^Application) -> ^Array {
|
||||
return msgSend(^Array, self, "windows")
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="run")
|
||||
Application_run :: proc "c" (self: ^Application) {
|
||||
msgSend(nil, self, "run")
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="terminate")
|
||||
Application_terminate :: proc "c" (self: ^Application, sender: ^Object) {
|
||||
msgSend(nil, self, "terminate:", sender)
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="isRunning")
|
||||
Application_isRunning :: proc "c" (self: ^Application) -> BOOL {
|
||||
return msgSend(BOOL, self, "isRunning")
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="currentEvent")
|
||||
Application_currentEvent :: proc "c" (self: ^Application) -> ^Event {
|
||||
return msgSend(^Event, self, "currentEvent")
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="nextEventMatchingMask")
|
||||
Application_nextEventMatchingMask :: proc "c" (self: ^Application, mask: EventMask, expiration: ^Date, in_mode: RunLoopMode, dequeue: BOOL) -> ^Event {
|
||||
return msgSend(^Event, self, "nextEventMatchingMask:untilDate:inMode:dequeue:", mask, expiration, in_mode, dequeue)
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="sendEvent")
|
||||
Application_sendEvent :: proc "c" (self: ^Application, event: ^Event) {
|
||||
msgSend(Event, self, "sendEvent:", event)
|
||||
}
|
||||
@(objc_type=Application, objc_name="updateWindows")
|
||||
Application_updateWindows :: proc "c" (self: ^Application) {
|
||||
msgSend(nil, self, "updateWindows")
|
||||
}
|
||||
|
||||
|
||||
@(objc_class="NSRunningApplication")
|
||||
RunningApplication :: struct {using _: Object}
|
||||
|
||||
@(objc_type=RunningApplication, objc_name="currentApplication", objc_is_class_method=true)
|
||||
RunningApplication_currentApplication :: proc "c" () -> ^RunningApplication {
|
||||
return msgSend(^RunningApplication, RunningApplication, "currentApplication")
|
||||
}
|
||||
|
||||
@(objc_type=RunningApplication, objc_name="localizedName")
|
||||
RunningApplication_localizedName :: proc "c" (self: ^RunningApplication) -> ^String {
|
||||
return msgSend(^String, self, "localizedName")
|
||||
}
|
||||
|
||||
ApplicationDelegateTemplate :: struct {
|
||||
// Launching Applications
|
||||
applicationWillFinishLaunching: proc(notification: ^Notification),
|
||||
applicationDidFinishLaunching: proc(notification: ^Notification),
|
||||
// Managing Active Status
|
||||
applicationWillBecomeActive: proc(notification: ^Notification),
|
||||
applicationDidBecomeActive: proc(notification: ^Notification),
|
||||
applicationWillResignActive: proc(notification: ^Notification),
|
||||
applicationDidResignActive: proc(notification: ^Notification),
|
||||
// Terminating Applications
|
||||
applicationShouldTerminate: proc(sender: ^Application) -> ApplicationTerminateReply,
|
||||
applicationShouldTerminateAfterLastWindowClosed: proc(sender: ^Application) -> BOOL,
|
||||
applicationWillTerminate: proc(notification: ^Notification),
|
||||
// Hiding Applications
|
||||
applicationWillHide: proc(notification: ^Notification),
|
||||
applicationDidHide: proc(notification: ^Notification),
|
||||
applicationWillUnhide: proc(notification: ^Notification),
|
||||
applicationDidUnhide: proc(notification: ^Notification),
|
||||
// Managing Windows
|
||||
applicationWillUpdate: proc(notification: ^Notification),
|
||||
applicationDidUpdate: proc(notification: ^Notification),
|
||||
applicationShouldHandleReopenHasVisibleWindows: proc(sender: ^Application, flag: BOOL) -> BOOL,
|
||||
// Managing the Dock Menu
|
||||
applicationDockMenu: proc(sender: ^Application) -> ^Menu,
|
||||
// Localizing Keyboard Shortcuts
|
||||
applicationShouldAutomaticallyLocalizeKeyEquivalents: proc(application: ^Application) -> BOOL,
|
||||
// Displaying Errors
|
||||
applicationWillPresentError: proc(application: ^Application, error: ^Error) -> ^Error,
|
||||
// Managing the Screen
|
||||
applicationDidChangeScreenParameters: proc(notification: ^Notification),
|
||||
// Continuing User Activities
|
||||
applicationWillContinueUserActivityWithType: proc(application: ^Application, userActivityType: ^String) -> BOOL,
|
||||
applicationContinueUserActivityRestorationHandler: proc(application: ^Application, userActivity: ^UserActivity, restorationHandler: ^Block) -> BOOL,
|
||||
applicationDidFailToContinueUserActivityWithTypeError: proc(application: ^Application, userActivityType: ^String, error: ^Error),
|
||||
applicationDidUpdateUserActivity: proc(application: ^Application, userActivity: ^UserActivity),
|
||||
// Handling Push Notifications
|
||||
applicationDidRegisterForRemoteNotificationsWithDeviceToken: proc(application: ^Application, deviceToken: ^Data),
|
||||
applicationDidFailToRegisterForRemoteNotificationsWithError: proc(application: ^Application, error: ^Error),
|
||||
applicationDidReceiveRemoteNotification: proc(application: ^Application, userInfo: ^Dictionary),
|
||||
// Handling CloudKit Invitations
|
||||
// TODO: if/when we have cloud kit bindings implement
|
||||
// applicationUserDidAcceptCloudKitShareWithMetadata: proc(application: ^Application, metadata: ^CKShareMetadata),
|
||||
// Handling SiriKit Intents
|
||||
// TODO: if/when we have siri kit bindings implement
|
||||
// applicationHandlerForIntent: proc(application: ^Application, intent: ^INIntent) -> id,
|
||||
// Opening Files
|
||||
applicationOpenURLs: proc(application: ^Application, urls: ^Array),
|
||||
applicationOpenFile: proc(sender: ^Application, filename: ^String) -> BOOL,
|
||||
applicationOpenFileWithoutUI: proc(sender: id, filename: ^String) -> BOOL,
|
||||
applicationOpenTempFile: proc(sender: ^Application, filename: ^String) -> BOOL,
|
||||
applicationOpenFiles: proc(sender: ^Application, filenames: ^Array),
|
||||
applicationShouldOpenUntitledFile: proc(sender: ^Application) -> BOOL,
|
||||
applicationOpenUntitledFile: proc(sender: ^Application) -> BOOL,
|
||||
// Printing
|
||||
applicationPrintFile: proc(sender: ^Application, filename: ^String) -> BOOL,
|
||||
applicationPrintFilesWithSettingsShowPrintPanels: proc(application: ^Application, fileNames: ^Array, printSettings: ^Dictionary, showPrintPanels: BOOL) -> ApplicationPrintReply,
|
||||
// Restoring Application State
|
||||
applicationSupportsSecureRestorableState: proc(app: ^Application) -> BOOL,
|
||||
applicationProtectedDataDidBecomeAvailable: proc(notification: ^Notification),
|
||||
applicationProtectedDataWillBecomeUnavailable: proc(notification: ^Notification),
|
||||
applicationWillEncodeRestorableState: proc(app: ^Application, coder: ^Coder),
|
||||
applicationDidDecodeRestorableState: proc(app: ^Application, coder: ^Coder),
|
||||
// Handling Changes to the Occlusion State
|
||||
applicationDidChangeOcclusionState: proc(notification: ^Notification),
|
||||
// Scripting Your App
|
||||
applicationDelegateHandlesKey: proc(sender: ^Application, key: ^String) -> BOOL,
|
||||
}
|
||||
|
||||
ApplicationDelegate :: struct { using _: Object }
|
||||
_ApplicationDelegateInternal :: struct {
|
||||
using _: ApplicationDelegateTemplate,
|
||||
_context: runtime.Context,
|
||||
}
|
||||
|
||||
application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTemplate, class_name: string, delegate_context: Maybe(runtime.Context)) -> ^ApplicationDelegate {
|
||||
class := objc_allocateClassPair(intrinsics.objc_find_class("NSObject"), strings.clone_to_cstring(class_name, context.temp_allocator), 0); if class == nil {
|
||||
// Class already registered
|
||||
return nil
|
||||
}
|
||||
if template.applicationWillFinishLaunching != nil {
|
||||
applicationWillFinishLaunching :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationWillFinishLaunching(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationWillFinishLaunching:"), auto_cast applicationWillFinishLaunching, "v@:@")
|
||||
}
|
||||
if template.applicationDidFinishLaunching != nil {
|
||||
applicationDidFinishLaunching :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidFinishLaunching(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationDidFinishLaunching:"), auto_cast applicationDidFinishLaunching, "v@:@")
|
||||
}
|
||||
if template.applicationWillBecomeActive != nil {
|
||||
applicationWillBecomeActive :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationWillBecomeActive(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationWillBecomeActive:"), auto_cast applicationWillBecomeActive, "v@:@")
|
||||
}
|
||||
if template.applicationDidBecomeActive != nil {
|
||||
applicationDidBecomeActive :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidBecomeActive(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationDidBecomeActive:"), auto_cast applicationDidBecomeActive, "v@:@")
|
||||
}
|
||||
if template.applicationWillResignActive != nil {
|
||||
applicationWillResignActive :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationWillResignActive(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationWillResignActive:"), auto_cast applicationWillResignActive, "v@:@")
|
||||
}
|
||||
if template.applicationDidResignActive != nil {
|
||||
applicationDidResignActive :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidResignActive(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationDidResignActive:"), auto_cast applicationDidResignActive, "v@:@")
|
||||
}
|
||||
if template.applicationShouldTerminate != nil {
|
||||
applicationShouldTerminate :: proc "c" (self: id, sender: ^Application) -> ApplicationTerminateReply {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationShouldTerminate(sender)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationShouldTerminate:"), auto_cast applicationShouldTerminate, _UINTEGER_ENCODING+"@:@")
|
||||
}
|
||||
if template.applicationShouldTerminateAfterLastWindowClosed != nil {
|
||||
applicationShouldTerminateAfterLastWindowClosed :: proc "c" (self: id, sender: ^Application) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationShouldTerminateAfterLastWindowClosed(sender)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationShouldTerminateAfterLastWindowClosed:"), auto_cast applicationShouldTerminateAfterLastWindowClosed, "B@:@")
|
||||
}
|
||||
if template.applicationWillTerminate != nil {
|
||||
applicationWillTerminate :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationWillTerminate(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationWillTerminate:"), auto_cast applicationWillTerminate, "v@:@")
|
||||
}
|
||||
if template.applicationWillHide != nil {
|
||||
applicationWillHide :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationWillHide(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationWillHide:"), auto_cast applicationWillHide, "v@:@")
|
||||
}
|
||||
if template.applicationDidHide != nil {
|
||||
applicationDidHide :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidHide(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationDidHide:"), auto_cast applicationDidHide, "v@:@")
|
||||
}
|
||||
if template.applicationWillUnhide != nil {
|
||||
applicationWillUnhide :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationWillUnhide(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationWillUnhide:"), auto_cast applicationWillUnhide, "v@:@")
|
||||
}
|
||||
if template.applicationDidUnhide != nil {
|
||||
applicationDidUnhide :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidUnhide(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationDidUnhide:"), auto_cast applicationDidUnhide, "v@:@")
|
||||
}
|
||||
if template.applicationWillUpdate != nil {
|
||||
applicationWillUpdate :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationWillUpdate(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationWillUpdate:"), auto_cast applicationWillUpdate, "v@:@")
|
||||
}
|
||||
if template.applicationDidUpdate != nil {
|
||||
applicationDidUpdate :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidUpdate(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationDidUpdate:"), auto_cast applicationDidUpdate, "v@:@")
|
||||
}
|
||||
if template.applicationShouldHandleReopenHasVisibleWindows != nil {
|
||||
applicationShouldHandleReopenHasVisibleWindows :: proc "c" (self: id, sender: ^Application, flag: BOOL) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationShouldHandleReopenHasVisibleWindows(sender, flag)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationShouldHandleReopen:hasVisibleWindows:"), auto_cast applicationShouldHandleReopenHasVisibleWindows, "B@:@B")
|
||||
}
|
||||
if template.applicationDockMenu != nil {
|
||||
applicationDockMenu :: proc "c" (self: id, sender: ^Application) -> ^Menu {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationDockMenu(sender)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationDockMenu:"), auto_cast applicationDockMenu, "@@:@")
|
||||
}
|
||||
if template.applicationShouldAutomaticallyLocalizeKeyEquivalents != nil {
|
||||
applicationShouldAutomaticallyLocalizeKeyEquivalents :: proc "c" (self: id, application: ^Application) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationShouldAutomaticallyLocalizeKeyEquivalents(application)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationShouldAutomaticallyLocalizeKeyEquivalents:"), auto_cast applicationShouldAutomaticallyLocalizeKeyEquivalents, "B@:@")
|
||||
}
|
||||
if template.applicationWillPresentError != nil {
|
||||
applicationWillPresentError :: proc "c" (self: id, application: ^Application, error: ^Error) -> ^Error {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationWillPresentError(application, error)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:willPresentError:"), auto_cast applicationWillPresentError, "@@:@@")
|
||||
}
|
||||
if template.applicationDidChangeScreenParameters != nil {
|
||||
applicationDidChangeScreenParameters :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidChangeScreenParameters(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationDidChangeScreenParameters:"), auto_cast applicationDidChangeScreenParameters, "v@:@")
|
||||
}
|
||||
if template.applicationWillContinueUserActivityWithType != nil {
|
||||
applicationWillContinueUserActivityWithType :: proc "c" (self: id, application: ^Application, userActivityType: ^String) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationWillContinueUserActivityWithType(application, userActivityType)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:willContinueUserActivityWithType:"), auto_cast applicationWillContinueUserActivityWithType, "B@:@@")
|
||||
}
|
||||
if template.applicationContinueUserActivityRestorationHandler != nil {
|
||||
applicationContinueUserActivityRestorationHandler :: proc "c" (self: id, application: ^Application, userActivity: ^UserActivity, restorationHandler: ^Block) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationContinueUserActivityRestorationHandler(application, userActivity, restorationHandler)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:continueUserActivity:restorationHandler:"), auto_cast applicationContinueUserActivityRestorationHandler, "B@:@@?")
|
||||
}
|
||||
if template.applicationDidFailToContinueUserActivityWithTypeError != nil {
|
||||
applicationDidFailToContinueUserActivityWithTypeError :: proc "c" (self: id, application: ^Application, userActivityType: ^String, error: ^Error) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidFailToContinueUserActivityWithTypeError(application, userActivityType, error)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:didFailToContinueUserActivityWithType:error:"), auto_cast applicationDidFailToContinueUserActivityWithTypeError, "v@:@@@")
|
||||
}
|
||||
if template.applicationDidUpdateUserActivity != nil {
|
||||
applicationDidUpdateUserActivity :: proc "c" (self: id, application: ^Application, userActivity: ^UserActivity) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidUpdateUserActivity(application, userActivity)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:didUpdateUserActivity:"), auto_cast applicationDidUpdateUserActivity, "v@:@@")
|
||||
}
|
||||
if template.applicationDidRegisterForRemoteNotificationsWithDeviceToken != nil {
|
||||
applicationDidRegisterForRemoteNotificationsWithDeviceToken :: proc "c" (self: id, application: ^Application, deviceToken: ^Data) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidRegisterForRemoteNotificationsWithDeviceToken(application, deviceToken)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:didRegisterForRemoteNotificationsWithDeviceToken:"), auto_cast applicationDidRegisterForRemoteNotificationsWithDeviceToken, "v@:@@")
|
||||
}
|
||||
if template.applicationDidFailToRegisterForRemoteNotificationsWithError != nil {
|
||||
applicationDidFailToRegisterForRemoteNotificationsWithError :: proc "c" (self: id, application: ^Application, error: ^Error) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidFailToRegisterForRemoteNotificationsWithError(application, error)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:didFailToRegisterForRemoteNotificationsWithError:"), auto_cast applicationDidFailToRegisterForRemoteNotificationsWithError, "v@:@@")
|
||||
}
|
||||
if template.applicationDidReceiveRemoteNotification != nil {
|
||||
applicationDidReceiveRemoteNotification :: proc "c" (self: id, application: ^Application, userInfo: ^Dictionary) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidReceiveRemoteNotification(application, userInfo)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:didReceiveRemoteNotification:"), auto_cast applicationDidReceiveRemoteNotification, "v@:@@")
|
||||
}
|
||||
// if template.applicationUserDidAcceptCloudKitShareWithMetadata != nil {
|
||||
// applicationUserDidAcceptCloudKitShareWithMetadata :: proc "c" (self: id, application: ^Application, metadata: ^CKShareMetadata) {
|
||||
// del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
// context = del._context
|
||||
// del.applicationUserDidAcceptCloudKitShareWithMetadata(application, metadata)
|
||||
// }
|
||||
// class_addMethod(class, intrinsics.objc_find_selector("application:userDidAcceptCloudKitShareWithMetadata:"), auto_cast applicationUserDidAcceptCloudKitShareWithMetadata, "v@:@@")
|
||||
// }
|
||||
// if template.applicationHandlerForIntent != nil {
|
||||
// applicationHandlerForIntent :: proc "c" (self: id, application: ^Application, intent: ^INIntent) -> id {
|
||||
// del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
// context = del._context
|
||||
// return del.applicationHandlerForIntent(application, intent)
|
||||
// }
|
||||
// class_addMethod(class, intrinsics.objc_find_selector("application:handlerForIntent:"), auto_cast applicationHandlerForIntent, "@@:@@")
|
||||
// }
|
||||
if template.applicationOpenURLs != nil {
|
||||
applicationOpenURLs :: proc "c" (self: id, application: ^Application, urls: ^Array) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationOpenURLs(application, urls)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:openURLs:"), auto_cast applicationOpenURLs, "v@:@@")
|
||||
}
|
||||
if template.applicationOpenFile != nil {
|
||||
applicationOpenFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationOpenFile(sender, filename)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:openFile:"), auto_cast applicationOpenFile, "B@:@@")
|
||||
}
|
||||
if template.applicationOpenFileWithoutUI != nil {
|
||||
applicationOpenFileWithoutUI :: proc "c" (self: id, sender: id, filename: ^String) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationOpenFileWithoutUI(sender, filename)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:openFileWithoutUI:"), auto_cast applicationOpenFileWithoutUI, "B@:@@")
|
||||
}
|
||||
if template.applicationOpenTempFile != nil {
|
||||
applicationOpenTempFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationOpenTempFile(sender, filename)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:openTempFile:"), auto_cast applicationOpenTempFile, "B@:@@")
|
||||
}
|
||||
if template.applicationOpenFiles != nil {
|
||||
applicationOpenFiles :: proc "c" (self: id, sender: ^Application, filenames: ^Array) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationOpenFiles(sender, filenames)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:openFiles:"), auto_cast applicationOpenFiles, "v@:@@")
|
||||
}
|
||||
if template.applicationShouldOpenUntitledFile != nil {
|
||||
applicationShouldOpenUntitledFile :: proc "c" (self: id, sender: ^Application) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationShouldOpenUntitledFile(sender)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationShouldOpenUntitledFile:"), auto_cast applicationShouldOpenUntitledFile, "B@:@")
|
||||
}
|
||||
if template.applicationOpenUntitledFile != nil {
|
||||
applicationOpenUntitledFile :: proc "c" (self: id, sender: ^Application) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationOpenUntitledFile(sender)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationOpenUntitledFile:"), auto_cast applicationOpenUntitledFile, "B@:@")
|
||||
}
|
||||
if template.applicationPrintFile != nil {
|
||||
applicationPrintFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationPrintFile(sender, filename)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:printFile:"), auto_cast applicationPrintFile, "B@:@@")
|
||||
}
|
||||
if template.applicationPrintFilesWithSettingsShowPrintPanels != nil {
|
||||
applicationPrintFilesWithSettingsShowPrintPanels :: proc "c" (self: id, application: ^Application, fileNames: ^Array, printSettings: ^Dictionary, showPrintPanels: BOOL) -> ApplicationPrintReply {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationPrintFilesWithSettingsShowPrintPanels(application, fileNames, printSettings, showPrintPanels)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:printFiles:withSettings:showPrintPanels:"), auto_cast applicationPrintFilesWithSettingsShowPrintPanels, _UINTEGER_ENCODING+"@:@@@B")
|
||||
}
|
||||
if template.applicationSupportsSecureRestorableState != nil {
|
||||
applicationSupportsSecureRestorableState :: proc "c" (self: id, app: ^Application) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationSupportsSecureRestorableState(app)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationSupportsSecureRestorableState:"), auto_cast applicationSupportsSecureRestorableState, "B@:@")
|
||||
}
|
||||
if template.applicationProtectedDataDidBecomeAvailable != nil {
|
||||
applicationProtectedDataDidBecomeAvailable :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationProtectedDataDidBecomeAvailable(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationProtectedDataDidBecomeAvailable:"), auto_cast applicationProtectedDataDidBecomeAvailable, "v@:@")
|
||||
}
|
||||
if template.applicationProtectedDataWillBecomeUnavailable != nil {
|
||||
applicationProtectedDataWillBecomeUnavailable :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationProtectedDataWillBecomeUnavailable(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationProtectedDataWillBecomeUnavailable:"), auto_cast applicationProtectedDataWillBecomeUnavailable, "v@:@")
|
||||
}
|
||||
if template.applicationWillEncodeRestorableState != nil {
|
||||
applicationWillEncodeRestorableState :: proc "c" (self: id, app: ^Application, coder: ^Coder) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationWillEncodeRestorableState(app, coder)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:willEncodeRestorableState:"), auto_cast applicationWillEncodeRestorableState, "v@:@@")
|
||||
}
|
||||
if template.applicationDidDecodeRestorableState != nil {
|
||||
applicationDidDecodeRestorableState :: proc "c" (self: id, app: ^Application, coder: ^Coder) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidDecodeRestorableState(app, coder)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:didDecodeRestorableState:"), auto_cast applicationDidDecodeRestorableState, "v@:@@")
|
||||
}
|
||||
if template.applicationDidChangeOcclusionState != nil {
|
||||
applicationDidChangeOcclusionState :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.applicationDidChangeOcclusionState(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("applicationDidChangeOcclusionState:"), auto_cast applicationDidChangeOcclusionState, "v@:@")
|
||||
}
|
||||
if template.applicationDelegateHandlesKey != nil {
|
||||
applicationDelegateHandlesKey :: proc "c" (self: id, sender: ^Application, key: ^String) -> BOOL {
|
||||
del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.applicationDelegateHandlesKey(sender, key)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("application:delegateHandlesKey:"), auto_cast applicationDelegateHandlesKey, "B@:@@")
|
||||
}
|
||||
|
||||
objc_registerClassPair(class)
|
||||
del := class_createInstance(class, size_of(_ApplicationDelegateInternal))
|
||||
del_internal := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(del)
|
||||
del_internal^ = {
|
||||
template,
|
||||
delegate_context.(runtime.Context) or_else runtime.default_context(),
|
||||
}
|
||||
return cast(^ApplicationDelegate)del
|
||||
}
|
||||
|
||||
@(objc_type=Application, objc_name="setDelegate")
|
||||
Application_setDelegate :: proc "c" (self: ^Application, delegate: ^ApplicationDelegate) {
|
||||
msgSend(nil, self, "setDelegate:", delegate)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package objc_Foundation
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@(objc_class="NSArray")
|
||||
Array :: struct {
|
||||
using _: Copying(Array),
|
||||
}
|
||||
|
||||
@(objc_type=Array, objc_name="alloc", objc_is_class_method=true)
|
||||
Array_alloc :: proc "c" () -> ^Array {
|
||||
return msgSend(^Array, Array, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Array, objc_name="init")
|
||||
Array_init :: proc "c" (self: ^Array) -> ^Array {
|
||||
return msgSend(^Array, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Array, objc_name="initWithObjects")
|
||||
Array_initWithObjects :: proc "c" (self: ^Array, objects: [^]^Object, count: UInteger) -> ^Array {
|
||||
return msgSend(^Array, self, "initWithObjects:count:", objects, count)
|
||||
}
|
||||
|
||||
@(objc_type=Array, objc_name="initWithCoder")
|
||||
Array_initWithCoder :: proc "c" (self: ^Array, coder: ^Coder) -> ^Array {
|
||||
return msgSend(^Array, self, "initWithCoder:", coder)
|
||||
}
|
||||
|
||||
@(objc_type=Array, objc_name="object")
|
||||
Array_object :: proc "c" (self: ^Array, index: UInteger) -> ^Object {
|
||||
return msgSend(^Object, self, "objectAtIndex:", index)
|
||||
}
|
||||
@(objc_type=Array, objc_name="objectAs")
|
||||
Array_objectAs :: proc "c" (self: ^Array, index: UInteger, $T: typeid) -> T where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) {
|
||||
return (T)(Array_object(self, index))
|
||||
}
|
||||
|
||||
@(objc_type=Array, objc_name="count")
|
||||
Array_count :: proc "c" (self: ^Array) -> UInteger {
|
||||
return msgSend(UInteger, self, "count")
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSAutoreleasePool")
|
||||
AutoreleasePool :: struct {using _: Object}
|
||||
|
||||
@(objc_type=AutoreleasePool, objc_name="alloc", objc_is_class_method=true)
|
||||
AutoreleasePool_alloc :: proc "c" () -> ^AutoreleasePool {
|
||||
return msgSend(^AutoreleasePool, AutoreleasePool, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=AutoreleasePool, objc_name="init")
|
||||
AutoreleasePool_init :: proc "c" (self: ^AutoreleasePool) -> ^AutoreleasePool {
|
||||
return msgSend(^AutoreleasePool, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=AutoreleasePool, objc_name="drain")
|
||||
AutoreleasePool_drain :: proc "c" (self: ^AutoreleasePool) {
|
||||
msgSend(nil, self, "drain")
|
||||
}
|
||||
@(objc_type=AutoreleasePool, objc_name="addObject")
|
||||
AutoreleasePool_addObject :: proc "c" (self: ^AutoreleasePool, obj: ^Object) {
|
||||
msgSend(nil, self, "addObject:", obj)
|
||||
}
|
||||
@(objc_type=AutoreleasePool, objc_name="showPools")
|
||||
AutoreleasePool_showPools :: proc "c" (self: ^AutoreleasePool, obj: ^Object) {
|
||||
msgSend(nil, self, "showPools")
|
||||
}
|
||||
|
||||
|
||||
@(deferred_out=AutoreleasePool_drain)
|
||||
scoped_autoreleasepool :: proc "c" () -> ^AutoreleasePool {
|
||||
return AutoreleasePool.alloc()->init()
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package objc_Foundation
|
||||
|
||||
import "base:intrinsics"
|
||||
import "base:builtin"
|
||||
import "core:mem"
|
||||
|
||||
@(objc_class="NSBlock")
|
||||
Block :: struct {using _: Object}
|
||||
|
||||
@(objc_type=Block, objc_name="createGlobal", objc_is_class_method=true)
|
||||
Block_createGlobal :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr), allocator := context.allocator) -> (^Block, mem.Allocator_Error) #optional_allocator_error {
|
||||
return Block_createInternal(true, user_data, user_proc, allocator)
|
||||
}
|
||||
@(objc_type=Block, objc_name="createLocal", objc_is_class_method=true)
|
||||
Block_createLocal :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr)) -> ^Block {
|
||||
b, _ := Block_createInternal(false, user_data, user_proc, {})
|
||||
return b
|
||||
}
|
||||
@(objc_type=Block, objc_name="createGlobalWithParam", objc_is_class_method=true)
|
||||
Block_createGlobalWithParam :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T), allocator := context.allocator) -> (^Block, mem.Allocator_Error) #optional_allocator_error {
|
||||
return Block_createInternalWithParam(true, user_data, user_proc, allocator)
|
||||
}
|
||||
@(objc_type=Block, objc_name="createLocalWithParam", objc_is_class_method=true)
|
||||
Block_createLocalWithParam :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T)) -> ^Block {
|
||||
b, _ := Block_createInternalWithParam(false, user_data, user_proc, {})
|
||||
return b
|
||||
}
|
||||
|
||||
@(private)
|
||||
Internal_Block_Literal_Base :: struct {
|
||||
isa: ^intrinsics.objc_class,
|
||||
flags: u32,
|
||||
reserved: u32,
|
||||
invoke: rawptr, // contains a pointer to a proc "c" (^Internal_Block_Literal, ...)
|
||||
descriptor: ^Block_Descriptor,
|
||||
}
|
||||
|
||||
@(private)
|
||||
Internal_Block_Literal :: struct {
|
||||
using base: Internal_Block_Literal_Base,
|
||||
// Imported Variables
|
||||
user_proc: rawptr, // contains a pointer to a proc "c" (user_data: rawptr, ...)
|
||||
user_data: rawptr,
|
||||
}
|
||||
|
||||
@(private)
|
||||
Block_Descriptor :: struct {
|
||||
reserved: uint,
|
||||
size: uint,
|
||||
copy_helper: proc "c" (dst, src: rawptr),
|
||||
dispose_helper: proc "c" (src: rawptr),
|
||||
signature: cstring,
|
||||
}
|
||||
|
||||
@(private)
|
||||
global_block_descriptor := Block_Descriptor{
|
||||
reserved = 0,
|
||||
size = size_of(Internal_Block_Literal),
|
||||
}
|
||||
|
||||
foreign import libSystem "system:System.framework"
|
||||
foreign libSystem {
|
||||
_NSConcreteGlobalBlock: intrinsics.objc_class
|
||||
_NSConcreteStackBlock: intrinsics.objc_class
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
internal_block_literal_make :: proc (is_global: bool, user_data: rawptr, user_proc: rawptr, invoke: rawptr, allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) {
|
||||
_init :: proc(bl: ^Internal_Block_Literal, is_global: bool, user_data: rawptr, user_proc: rawptr, invoke: rawptr) {
|
||||
// Set to true on blocks that have captures (and thus are not true
|
||||
// global blocks) but are known not to escape for various other
|
||||
// reasons. For backward compatibility with old runtimes, whenever
|
||||
// BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a
|
||||
// non-escaping block returns the original block and releasing such a
|
||||
// block is a no-op, which is exactly how global blocks are handled.
|
||||
BLOCK_IS_NOESCAPE :: (1 << 23)|BLOCK_IS_GLOBAL
|
||||
|
||||
BLOCK_HAS_COPY_DISPOSE :: 1 << 25
|
||||
BLOCK_HAS_CTOR :: 1 << 26 // helpers have C++ code
|
||||
BLOCK_IS_GLOBAL :: 1 << 28
|
||||
BLOCK_HAS_STRET :: 1 << 29 // IFF BLOCK_HAS_SIGNATURE
|
||||
BLOCK_HAS_SIGNATURE :: 1 << 30
|
||||
|
||||
bl.isa = is_global ? &_NSConcreteGlobalBlock : &_NSConcreteStackBlock
|
||||
bl.flags = BLOCK_IS_GLOBAL if is_global else 0
|
||||
bl.invoke = invoke
|
||||
bl.descriptor = &global_block_descriptor
|
||||
bl.user_proc = auto_cast user_proc
|
||||
bl.user_data = user_data
|
||||
}
|
||||
if is_global {
|
||||
bl := builtin.new (Internal_Block_Literal, allocator) or_return
|
||||
_init(bl, true, user_data, user_proc, invoke)
|
||||
return auto_cast bl, .None
|
||||
} else {
|
||||
// malloc blocks are created by calling 'copy' on a stack block
|
||||
bl: Internal_Block_Literal
|
||||
_init(&bl, false, user_data, user_proc, invoke)
|
||||
return auto_cast copy(cast(^Copying(Block))(&bl)), .None
|
||||
}
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
Block_createInternal :: proc (is_global: bool, user_data: rawptr, user_proc: proc "c" (user_data: rawptr), allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) {
|
||||
invoke :: proc "c" (bl: ^Internal_Block_Literal) {
|
||||
user_proc := (proc "c" (rawptr))(bl.user_proc)
|
||||
user_proc(bl.user_data)
|
||||
}
|
||||
return internal_block_literal_make(is_global, user_data, auto_cast user_proc, auto_cast invoke, allocator)
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
Block_createInternalWithParam :: proc (is_global: bool, user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T), allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) {
|
||||
invoke :: proc "c" (bl: ^Internal_Block_Literal, t: T) {
|
||||
user_proc := (proc "c" (rawptr, T))(bl.user_proc)
|
||||
user_proc(bl.user_data, t)
|
||||
}
|
||||
return internal_block_literal_make(is_global, user_data, auto_cast user_proc, auto_cast invoke, allocator)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSBundle")
|
||||
Bundle :: struct { using _: Object }
|
||||
|
||||
@(objc_type=Bundle, objc_name="mainBundle", objc_is_class_method=true)
|
||||
Bundle_mainBundle :: proc "c" () -> ^Bundle {
|
||||
return msgSend(^Bundle, Bundle, "mainBundle")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="bundleWithPath", objc_is_class_method=true)
|
||||
Bundle_bundleWithPath :: proc "c" (path: ^String) -> ^Bundle {
|
||||
return msgSend(^Bundle, Bundle, "bundleWithPath:", path)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="bundleWithURL", objc_is_class_method=true)
|
||||
Bundle_bundleWithURL :: proc "c" (url: ^URL) -> ^Bundle {
|
||||
return msgSend(^Bundle, Bundle, "bundleWithUrl:", url)
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Bundle, objc_name="alloc", objc_is_class_method=true)
|
||||
Bundle_alloc :: proc "c" () -> ^Bundle {
|
||||
return msgSend(^Bundle, Bundle, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="init")
|
||||
Bundle_init :: proc "c" (self: ^Bundle) -> ^Bundle {
|
||||
return msgSend(^Bundle, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="initWithPath")
|
||||
Bundle_initWithPath :: proc "c" (self: ^Bundle, path: ^String) -> ^Bundle {
|
||||
return msgSend(^Bundle, self, "initWithPath:", path)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="initWithURL")
|
||||
Bundle_initWithURL :: proc "c" (self: ^Bundle, url: ^URL) -> ^Bundle {
|
||||
return msgSend(^Bundle, self, "initWithUrl:", url)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="allBundles")
|
||||
Bundle_allBundles :: proc "c" () -> (all: ^Array) {
|
||||
return msgSend(type_of(all), Bundle, "allBundles")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="allFrameworks")
|
||||
Bundle_allFrameworks :: proc "c" () -> (all: ^Array) {
|
||||
return msgSend(type_of(all), Bundle, "allFrameworks")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="load")
|
||||
Bundle_load :: proc "c" (self: ^Bundle) -> BOOL {
|
||||
return msgSend(BOOL, self, "load")
|
||||
}
|
||||
@(objc_type=Bundle, objc_name="unload")
|
||||
Bundle_unload :: proc "c" (self: ^Bundle) -> BOOL {
|
||||
return msgSend(BOOL, self, "unload")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="isLoaded")
|
||||
Bundle_isLoaded :: proc "c" (self: ^Bundle) -> BOOL {
|
||||
return msgSend(BOOL, self, "isLoaded")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="preflightAndReturnError")
|
||||
Bundle_preflightAndReturnError :: proc "contextless" (self: ^Bundle) -> (ok: BOOL, error: ^Error) {
|
||||
ok = msgSend(BOOL, self, "preflightAndReturnError:", &error)
|
||||
return
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="loadAndReturnError")
|
||||
Bundle_loadAndReturnError :: proc "contextless" (self: ^Bundle) -> (ok: BOOL, error: ^Error) {
|
||||
ok = msgSend(BOOL, self, "loadAndReturnError:", &error)
|
||||
return
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="bundleURL")
|
||||
Bundle_bundleURL :: proc "c" (self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "bundleURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="resourceURL")
|
||||
Bundle_resourceURL :: proc "c" (self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "resourceURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="executableURL")
|
||||
Bundle_executableURL :: proc "c" (self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "executableURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="URLForAuxiliaryExecutable")
|
||||
Bundle_URLForAuxiliaryExecutable :: proc "c" (self: ^Bundle, executableName: ^String) -> ^URL {
|
||||
return msgSend(^URL, self, "URLForAuxiliaryExecutable:", executableName)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="privateFrameworksURL")
|
||||
Bundle_privateFrameworksURL :: proc "c" (self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "privateFrameworksURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="sharedFrameworksURL")
|
||||
Bundle_sharedFrameworksURL :: proc "c" (self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "sharedFrameworksURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="sharedSupportURL")
|
||||
Bundle_sharedSupportURL :: proc "c" (self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "sharedSupportURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="builtInPlugInsURL")
|
||||
Bundle_builtInPlugInsURL :: proc "c" (self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "builtInPlugInsURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="appStoreReceiptURL")
|
||||
Bundle_appStoreReceiptURL :: proc "c" (self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "appStoreReceiptURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="bundlePath")
|
||||
Bundle_bundlePath :: proc "c" (self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "bundlePath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="resourcePath")
|
||||
Bundle_resourcePath :: proc "c" (self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "resourcePath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="executablePath")
|
||||
Bundle_executablePath :: proc "c" (self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "executablePath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="PathForAuxiliaryExecutable")
|
||||
Bundle_PathForAuxiliaryExecutable :: proc "c" (self: ^Bundle, executableName: ^String) -> ^String {
|
||||
return msgSend(^String, self, "PathForAuxiliaryExecutable:", executableName)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="privateFrameworksPath")
|
||||
Bundle_privateFrameworksPath :: proc "c" (self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "privateFrameworksPath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="sharedFrameworksPath")
|
||||
Bundle_sharedFrameworksPath :: proc "c" (self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "sharedFrameworksPath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="sharedSupportPath")
|
||||
Bundle_sharedSupportPath :: proc "c" (self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "sharedSupportPath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="builtInPlugInsPath")
|
||||
Bundle_builtInPlugInsPath :: proc "c" (self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "builtInPlugInsPath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="appStoreReceiptPath")
|
||||
Bundle_appStoreReceiptPath :: proc "c" (self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "appStoreReceiptPath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="bundleIdentifier")
|
||||
Bundle_bundleIdentifier :: proc "c" (self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "bundleIdentifier")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="infoDictionary")
|
||||
Bundle_infoDictionary :: proc "c" (self: ^Bundle) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "infoDictionary")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="localizedInfoDictionary")
|
||||
Bundle_localizedInfoDictionary :: proc "c" (self: ^Bundle) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "localizedInfoDictionary")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="objectForInfoDictionaryKey")
|
||||
Bundle_objectForInfoDictionaryKey :: proc "c" (self: ^Bundle, key: ^String) -> ^Object {
|
||||
return msgSend(^Object, self, "objectForInfoDictionaryKey:", key)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="localizedStringForKey")
|
||||
Bundle_localizedStringForKey :: proc "c" (self: ^Bundle, key: ^String, value: ^String = nil, tableName: ^String = nil) -> ^String {
|
||||
return msgSend(^String, self, "localizedStringForKey:value:table:", key, value, tableName)
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSColorSpace")
|
||||
ColorSpace :: struct {using _: Object}
|
||||
|
||||
@(objc_class="NSColor")
|
||||
Color :: struct {using _: Object}
|
||||
|
||||
@(objc_type=Color, objc_name="colorWithSRGBRed", objc_is_class_method=true)
|
||||
Color_colorWithSRGBRed :: proc "c" (red, green, blue, alpha: Float) -> ^Color {
|
||||
return msgSend(^Color, Color, "colorWithSRGBRed:green:blue:alpha:", red, green, blue, alpha)
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="colorWithCalibratedHue", objc_is_class_method=true)
|
||||
Color_colorWithCalibratedHue :: proc "c" (hue, saturation, brightness, alpha: Float) -> ^Color {
|
||||
return msgSend(^Color, Color, "colorWithCalibratedHue:hue:saturation:brightness:alpha:", hue, saturation, brightness, alpha)
|
||||
}
|
||||
@(objc_type=Color, objc_name="colorWithCalibratedRed", objc_is_class_method=true)
|
||||
Color_colorWithCalibratedRed :: proc "c" (red, green, blue, alpha: Float) -> ^Color {
|
||||
return msgSend(^Color, Color, "colorWithCalibratedRed:green:blue:alpha:", red, green, blue, alpha)
|
||||
}
|
||||
@(objc_type=Color, objc_name="colorWithCalibratedWhite", objc_is_class_method=true)
|
||||
Color_colorWithCalibratedWhite :: proc "c" (white, alpha: Float) -> ^Color {
|
||||
return msgSend(^Color, Color, "colorWithCalibratedWhite:alpha:", white, alpha)
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="colorWithDeviceCyan", objc_is_class_method=true)
|
||||
Color_colorWithDeviceCyan :: proc "c" (cyan, magenta, yellow, black, alpha: Float) -> ^Color {
|
||||
return msgSend(^Color, Color, "colorWithDeviceCyan:magenta:yellow:black:", cyan, magenta, yellow, black)
|
||||
}
|
||||
@(objc_type=Color, objc_name="colorWithDeviceHue", objc_is_class_method=true)
|
||||
Color_colorWithDeviceHue :: proc "c" (hue, saturation, brightness, alpha: Float) -> ^Color {
|
||||
return msgSend(^Color, Color, "colorWithDeviceHue:hue:saturation:brightness:alpha:", hue, saturation, brightness, alpha)
|
||||
}
|
||||
@(objc_type=Color, objc_name="colorWithDeviceRed", objc_is_class_method=true)
|
||||
Color_colorWithDeviceRed :: proc "c" (red, green, blue, alpha: Float) -> ^Color {
|
||||
return msgSend(^Color, Color, "colorWithDeviceRed:green:blue:alpha:", red, green, blue, alpha)
|
||||
}
|
||||
@(objc_type=Color, objc_name="colorWithDeviceWhite", objc_is_class_method=true)
|
||||
Color_colorWithDeviceWhite :: proc "c" (white, alpha: Float) -> ^Color {
|
||||
return msgSend(^Color, Color, "colorWithDeviceWhite:alpha:", white, alpha)
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Color, objc_name="blackColor", objc_is_class_method=true)
|
||||
Color_blackColor :: proc "c" () -> ^Color {
|
||||
return msgSend(^Color, Color, "blackColor")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="whiteColor", objc_is_class_method=true)
|
||||
Color_whiteColor :: proc "c" () -> ^Color {
|
||||
return msgSend(^Color, Color, "whiteColor")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="redColor", objc_is_class_method=true)
|
||||
Color_redColor :: proc "c" () -> ^Color {
|
||||
return msgSend(^Color, Color, "redColor")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="greenColor", objc_is_class_method=true)
|
||||
Color_greenColor :: proc "c" () -> ^Color {
|
||||
return msgSend(^Color, Color, "greenColor")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="orangeColor", objc_is_class_method=true)
|
||||
Color_orangeColor :: proc "c" () -> ^Color {
|
||||
return msgSend(^Color, Color, "orangeColor")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="purpleColor", objc_is_class_method=true)
|
||||
Color_purpleColor :: proc "c" () -> ^Color {
|
||||
return msgSend(^Color, Color, "purpleColor")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="cyanColor", objc_is_class_method=true)
|
||||
Color_cyanColor :: proc "c" () -> ^Color {
|
||||
return msgSend(^Color, Color, "cyanColor")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="blueColor", objc_is_class_method=true)
|
||||
Color_blueColor :: proc "c" () -> ^Color {
|
||||
return msgSend(^Color, Color, "blueColor")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="magentaColor", objc_is_class_method=true)
|
||||
Color_magentaColor :: proc "c" () -> ^Color {
|
||||
return msgSend(^Color, Color, "magentaColor")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="yellowColor", objc_is_class_method=true)
|
||||
Color_yellowColor :: proc "c" () -> ^Color {
|
||||
return msgSend(^Color, Color, "yellowColor")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Color, objc_name="getCMYKA")
|
||||
Color_getCMYKA :: proc "c" (self: ^Color) -> (cyan, magenta, yellow, black, alpha: Float) {
|
||||
msgSend(nil, Color, "getCyan:magenta:yellow:black:alpha:", &cyan, &magenta, &yellow, &black, &alpha)
|
||||
return
|
||||
}
|
||||
@(objc_type=Color, objc_name="getHSBA")
|
||||
Color_getHSBA :: proc "c" (self: ^Color) -> (hue, saturation, brightness, alpha: Float) {
|
||||
msgSend(nil, Color, "getHue:saturation:brightness:alpha:", &hue, &saturation, &brightness, &alpha)
|
||||
return
|
||||
}
|
||||
@(objc_type=Color, objc_name="getRGBA")
|
||||
Color_getRGBA :: proc "c" (self: ^Color) -> (red, green, blue, alpha: Float) {
|
||||
msgSend(nil, Color, "getRed:green:blue:alpha:", &red, &green, &blue, &alpha)
|
||||
return
|
||||
}
|
||||
@(objc_type=Color, objc_name="getWhiteAlpha")
|
||||
Color_getWhiteAlpha :: proc "c" (self: ^Color) -> (white, alpha: Float) {
|
||||
msgSend(nil, Color, "getWhite:alpha:", &white, &alpha)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Color, objc_name="colorWithColorSpace", objc_is_class_method=true)
|
||||
Color_colorWithColorSpace :: proc "c" (space: ^ColorSpace, components: []Float) -> ^Color {
|
||||
return msgSend(^Color, Color, "colorWithColorSpace:components:count", space, raw_data(components), Integer(len(components)))
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Color, objc_name="colorSpaceName")
|
||||
Color_colorSpaceName :: proc "c" (self: ^Color) -> ^String {
|
||||
return msgSend(^String, self, "colorSpaceName")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="colorSpace")
|
||||
Color_colorSpace :: proc "c" (self: ^Color) -> ^ColorSpace {
|
||||
return msgSend(^ColorSpace, self, "colorSpace")
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="colorUsingColorSpaceName")
|
||||
Color_colorUsingColorSpaceName :: proc "c" (self: ^Color, colorSpace: ^String, device: ^Dictionary = nil) -> ^Color {
|
||||
if device != nil {
|
||||
return msgSend(^Color, self, "colorUsingColorSpaceName:device:", colorSpace, device)
|
||||
}
|
||||
return msgSend(^Color, self, "colorUsingColorSpaceName:", colorSpace)
|
||||
}
|
||||
|
||||
@(objc_type=Color, objc_name="numberOfComponents")
|
||||
Color_numberOfComponents :: proc "c" (self: ^Color) -> Integer {
|
||||
return msgSend(Integer, self, "numberOfComponents")
|
||||
}
|
||||
@(objc_type=Color, objc_name="getComponents")
|
||||
Color_getComponents :: proc "c" (self: ^Color, components: [^]Float) {
|
||||
msgSend(nil, self, "getComponents:", components)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSData")
|
||||
Data :: struct {using _: Copying(Data)}
|
||||
|
||||
@(objc_type=Data, objc_name="alloc", objc_is_class_method=true)
|
||||
Data_alloc :: proc "c" () -> ^Data {
|
||||
return msgSend(^Data, Data, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Data, objc_name="init")
|
||||
Data_init :: proc "c" (self: ^Data) -> ^Data {
|
||||
return msgSend(^Data, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Data, objc_name="mutableBytes")
|
||||
Data_mutableBytes :: proc "c" (self: ^Data) -> rawptr {
|
||||
return msgSend(rawptr, self, "mutableBytes")
|
||||
}
|
||||
|
||||
@(objc_type=Data, objc_name="length")
|
||||
Data_length :: proc "c" (self: ^Data) -> UInteger {
|
||||
return msgSend(UInteger, self, "length")
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSDate")
|
||||
Date :: struct {using _: Copying(Date)}
|
||||
|
||||
@(objc_type=Date, objc_name="alloc", objc_is_class_method=true)
|
||||
Date_alloc :: proc "c" () -> ^Date {
|
||||
return msgSend(^Date, Date, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Date, objc_name="init")
|
||||
Date_init :: proc "c" (self: ^Date) -> ^Date {
|
||||
return msgSend(^Date, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Date, objc_name="dateWithTimeIntervalSinceNow")
|
||||
Date_dateWithTimeIntervalSinceNow :: proc "c" (secs: TimeInterval) -> ^Date {
|
||||
return msgSend(^Date, Date, "dateWithTimeIntervalSinceNow:", secs)
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSDictionary")
|
||||
Dictionary :: struct {using _: Copying(Dictionary)}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="dictionary", objc_is_class_method=true)
|
||||
Dictionary_dictionary :: proc "c" () -> ^Dictionary {
|
||||
return msgSend(^Dictionary, Dictionary, "dictionary")
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="dictionaryWithObject", objc_is_class_method=true)
|
||||
Dictionary_dictionaryWithObject :: proc "c" (object: ^Object, forKey: ^Object) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, Dictionary, "dictionaryWithObject:forKey:", object, forKey)
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="dictionaryWithObjects", objc_is_class_method=true)
|
||||
Dictionary_dictionaryWithObjects :: proc "c" (objects: [^]^Object, forKeys: [^]^Object, count: UInteger) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, Dictionary, "dictionaryWithObjects:forKeys:count", objects, forKeys, count)
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Dictionary, objc_name="alloc", objc_is_class_method=true)
|
||||
Dictionary_alloc :: proc "c" () -> ^Dictionary {
|
||||
return msgSend(^Dictionary, Dictionary, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="init")
|
||||
Dictionary_init :: proc "c" (self: ^Dictionary) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="initWithObjects")
|
||||
Dictionary_initWithObjects :: proc "c" (self: ^Dictionary, objects: [^]^Object, forKeys: [^]^Object, count: UInteger) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "initWithObjects:forKeys:count", objects, forKeys, count)
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="objectForKey")
|
||||
Dictionary_objectForKey :: proc "c" (self: ^Dictionary, key: ^Object) -> ^Object {
|
||||
return msgSend(^Dictionary, self, "objectForKey:", key)
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="count")
|
||||
Dictionary_count :: proc "c" (self: ^Dictionary) -> UInteger {
|
||||
return msgSend(UInteger, self, "count")
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="keyEnumerator")
|
||||
Dictionary_keyEnumerator :: proc "c" (self: ^Dictionary, $KeyType: typeid) -> (enumerator: ^Enumerator(KeyType)) {
|
||||
return msgSend(type_of(enumerator), self, "keyEnumerator")
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package objc_Foundation
|
||||
|
||||
import "core:c"
|
||||
import "base:intrinsics"
|
||||
|
||||
FastEnumerationState :: struct #packed {
|
||||
state: c.ulong,
|
||||
itemsPtr: [^]^Object,
|
||||
mutationsPtr: [^]c.ulong,
|
||||
extra: [5]c.ulong,
|
||||
}
|
||||
|
||||
@(objc_class="NSFastEnumeration")
|
||||
FastEnumeration :: struct {using _: Object}
|
||||
|
||||
@(objc_class="NSEnumerator")
|
||||
Enumerator :: struct($T: typeid) where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) {
|
||||
using _: FastEnumeration,
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=FastEnumeration, objc_name="alloc", objc_is_class_method=true)
|
||||
FastEnumeration_alloc :: proc "c" () -> ^FastEnumeration {
|
||||
return msgSend(^FastEnumeration, FastEnumeration, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=FastEnumeration, objc_name="init")
|
||||
FastEnumeration_init :: proc "c" (self: ^FastEnumeration) -> ^FastEnumeration {
|
||||
return msgSend(^FastEnumeration, self, "init")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=FastEnumeration, objc_name="countByEnumerating")
|
||||
FastEnumeration_countByEnumerating :: proc "c" (self: ^FastEnumeration, state: ^FastEnumerationState, buffer: [^]^Object, len: UInteger) -> UInteger {
|
||||
return msgSend(UInteger, self, "countByEnumeratingWithState:objects:count:", state, buffer, len)
|
||||
}
|
||||
|
||||
Enumerator_nextObject :: proc "c" (self: ^$E/Enumerator($T)) -> T {
|
||||
return msgSend(T, self, "nextObject")
|
||||
}
|
||||
|
||||
Enumerator_allObjects :: proc "c" (self: ^$E/Enumerator($T)) -> (all: ^Array) {
|
||||
return msgSend(type_of(all), self, "allObjects")
|
||||
}
|
||||
|
||||
Enumerator_iterator :: proc "contextless" (self: ^$E/Enumerator($T)) -> (obj: T, ok: bool) {
|
||||
obj = msgSend(T, self, "nextObject")
|
||||
ok = obj != nil
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package objc_Foundation
|
||||
|
||||
foreign import "system:Foundation.framework"
|
||||
|
||||
ErrorDomain :: ^String
|
||||
|
||||
foreign Foundation {
|
||||
@(linkage="weak") CocoaErrorDomain: ErrorDomain
|
||||
@(linkage="weak") POSIXErrorDomain: ErrorDomain
|
||||
@(linkage="weak") OSStatusErrorDomain: ErrorDomain
|
||||
@(linkage="weak") MachErrorDomain: ErrorDomain
|
||||
}
|
||||
|
||||
ErrorUserInfoKey :: ^String
|
||||
|
||||
foreign Foundation {
|
||||
@(linkage="weak") UnderlyingErrorKey: ErrorUserInfoKey
|
||||
@(linkage="weak") LocalizedDescriptionKey: ErrorUserInfoKey
|
||||
@(linkage="weak") LocalizedFailureReasonErrorKey: ErrorUserInfoKey
|
||||
@(linkage="weak") LocalizedRecoverySuggestionErrorKey: ErrorUserInfoKey
|
||||
@(linkage="weak") LocalizedRecoveryOptionsErrorKey: ErrorUserInfoKey
|
||||
@(linkage="weak") RecoveryAttempterErrorKey: ErrorUserInfoKey
|
||||
@(linkage="weak") HelpAnchorErrorKey: ErrorUserInfoKey
|
||||
@(linkage="weak") DebugDescriptionErrorKey: ErrorUserInfoKey
|
||||
@(linkage="weak") LocalizedFailureErrorKey: ErrorUserInfoKey
|
||||
@(linkage="weak") StringEncodingErrorKey: ErrorUserInfoKey
|
||||
@(linkage="weak") URLErrorKey: ErrorUserInfoKey
|
||||
@(linkage="weak") FilePathErrorKey: ErrorUserInfoKey
|
||||
}
|
||||
|
||||
@(objc_class="NSError")
|
||||
Error :: struct { using _: Copying(Error) }
|
||||
|
||||
|
||||
@(objc_type=Error, objc_name="alloc", objc_is_class_method=true)
|
||||
Error_alloc :: proc "c" () -> ^Error {
|
||||
return msgSend(^Error, Error, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="init")
|
||||
Error_init :: proc "c" (self: ^Error) -> ^Error {
|
||||
return msgSend(^Error, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="errorWithDomain", objc_is_class_method=true)
|
||||
Error_errorWithDomain :: proc "c" (domain: ErrorDomain, code: Integer, userInfo: ^Dictionary) -> ^Error {
|
||||
return msgSend(^Error, Error, "errorWithDomain:code:userInfo:", domain, code, userInfo)
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="initWithDomain")
|
||||
Error_initWithDomain :: proc "c" (self: ^Error, domain: ErrorDomain, code: Integer, userInfo: ^Dictionary) -> ^Error {
|
||||
return msgSend(^Error, self, "initWithDomain:code:userInfo:", domain, code, userInfo)
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="code")
|
||||
Error_code :: proc "c" (self: ^Error) -> Integer {
|
||||
return msgSend(Integer, self, "code")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="domain")
|
||||
Error_domain :: proc "c" (self: ^Error) -> ErrorDomain {
|
||||
return msgSend(ErrorDomain, self, "domain")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="userInfo")
|
||||
Error_userInfo :: proc "c" (self: ^Error) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "userInfo")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="localizedDescription")
|
||||
Error_localizedDescription :: proc "c" (self: ^Error) -> ^String {
|
||||
return msgSend(^String, self, "localizedDescription")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="localizedRecoveryOptions")
|
||||
Error_localizedRecoveryOptions :: proc "c" (self: ^Error) -> (options: ^Array) {
|
||||
return msgSend(type_of(options), self, "localizedRecoveryOptions")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="localizedRecoverySuggestion")
|
||||
Error_localizedRecoverySuggestion :: proc "c" (self: ^Error) -> ^String {
|
||||
return msgSend(^String, self, "localizedRecoverySuggestion")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="localizedFailureReason")
|
||||
Error_localizedFailureReason :: proc "c" (self: ^Error) -> ^String {
|
||||
return msgSend(^String, self, "localizedFailureReason")
|
||||
}
|
||||
@@ -0,0 +1,466 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSEvent")
|
||||
Event :: struct {using _: Object}
|
||||
|
||||
|
||||
|
||||
EventMask :: distinct bit_set[EventType; UInteger]
|
||||
EventMaskAny :: ~EventMask{}
|
||||
|
||||
when size_of(UInteger) == 4 {
|
||||
// We don't support a 32-bit darwin system but this is mostly to shut up the type checker for the time being
|
||||
EventType :: enum UInteger {
|
||||
LeftMouseDown = 1,
|
||||
LeftMouseUp = 2,
|
||||
RightMouseDown = 3,
|
||||
RightMouseUp = 4,
|
||||
MouseMoved = 5,
|
||||
LeftMouseDragged = 6,
|
||||
RightMouseDragged = 7,
|
||||
MouseEntered = 8,
|
||||
MouseExited = 9,
|
||||
KeyDown = 10,
|
||||
KeyUp = 11,
|
||||
FlagsChanged = 12,
|
||||
AppKitDefined = 13,
|
||||
SystemDefined = 14,
|
||||
ApplicationDefined = 15,
|
||||
Periodic = 16,
|
||||
CursorUpdate = 17,
|
||||
Rotate = 18,
|
||||
BeginGesture = 19,
|
||||
EndGesture = 20,
|
||||
ScrollWheel = 22,
|
||||
TabletPoint = 23,
|
||||
TabletProximity = 24,
|
||||
OtherMouseDown = 25,
|
||||
OtherMouseUp = 26,
|
||||
OtherMouseDragged = 27,
|
||||
Gesture = 29,
|
||||
Magnify = 30,
|
||||
Swipe = 31,
|
||||
}
|
||||
} else {
|
||||
EventType :: enum UInteger {
|
||||
LeftMouseDown = 1,
|
||||
LeftMouseUp = 2,
|
||||
RightMouseDown = 3,
|
||||
RightMouseUp = 4,
|
||||
MouseMoved = 5,
|
||||
LeftMouseDragged = 6,
|
||||
RightMouseDragged = 7,
|
||||
MouseEntered = 8,
|
||||
MouseExited = 9,
|
||||
KeyDown = 10,
|
||||
KeyUp = 11,
|
||||
FlagsChanged = 12,
|
||||
AppKitDefined = 13,
|
||||
SystemDefined = 14,
|
||||
ApplicationDefined = 15,
|
||||
Periodic = 16,
|
||||
CursorUpdate = 17,
|
||||
Rotate = 18,
|
||||
BeginGesture = 19,
|
||||
EndGesture = 20,
|
||||
ScrollWheel = 22,
|
||||
TabletPoint = 23,
|
||||
TabletProximity = 24,
|
||||
OtherMouseDown = 25,
|
||||
OtherMouseUp = 26,
|
||||
OtherMouseDragged = 27,
|
||||
Gesture = 29,
|
||||
Magnify = 30,
|
||||
Swipe = 31,
|
||||
SmartMagnify = 32,
|
||||
QuickLook = 33,
|
||||
Pressure = 34,
|
||||
DirectTouch = 37,
|
||||
ChangeMode = 38,
|
||||
}
|
||||
}
|
||||
|
||||
EventPhase :: distinct bit_set[EventPhaseFlag; UInteger]
|
||||
EventPhaseFlag :: enum UInteger {
|
||||
Began = 0,
|
||||
Stationary = 1,
|
||||
Changed = 2,
|
||||
Ended = 3,
|
||||
Cancelled = 4,
|
||||
MayBegin = 5,
|
||||
}
|
||||
EventPhaseNone :: EventPhase{}
|
||||
EventPhaseBegan :: EventPhase{.Began}
|
||||
EventPhaseStationary :: EventPhase{.Stationary}
|
||||
EventPhaseChanged :: EventPhase{.Changed}
|
||||
EventPhaseEnded :: EventPhase{.Ended}
|
||||
EventPhaseCancelled :: EventPhase{.Cancelled}
|
||||
EventPhaseMayBegin :: EventPhase{.MayBegin}
|
||||
|
||||
/* pointer types for NSTabletProximity events or mouse events with subtype NSTabletProximityEventSubtype*/
|
||||
PointingDeviceType :: enum UInteger {
|
||||
Unknown = 0,
|
||||
Pen = 1,
|
||||
Cursor = 2,
|
||||
Eraser = 3,
|
||||
}
|
||||
|
||||
// Defined in Carbon.framework Events.h
|
||||
kVK :: enum {
|
||||
ANSI_A = 0x00,
|
||||
ANSI_S = 0x01,
|
||||
ANSI_D = 0x02,
|
||||
ANSI_F = 0x03,
|
||||
ANSI_H = 0x04,
|
||||
ANSI_G = 0x05,
|
||||
ANSI_Z = 0x06,
|
||||
ANSI_X = 0x07,
|
||||
ANSI_C = 0x08,
|
||||
ANSI_V = 0x09,
|
||||
ANSI_B = 0x0B,
|
||||
ANSI_Q = 0x0C,
|
||||
ANSI_W = 0x0D,
|
||||
ANSI_E = 0x0E,
|
||||
ANSI_R = 0x0F,
|
||||
ANSI_Y = 0x10,
|
||||
ANSI_T = 0x11,
|
||||
ANSI_1 = 0x12,
|
||||
ANSI_2 = 0x13,
|
||||
ANSI_3 = 0x14,
|
||||
ANSI_4 = 0x15,
|
||||
ANSI_6 = 0x16,
|
||||
ANSI_5 = 0x17,
|
||||
ANSI_Equal = 0x18,
|
||||
ANSI_9 = 0x19,
|
||||
ANSI_7 = 0x1A,
|
||||
ANSI_Minus = 0x1B,
|
||||
ANSI_8 = 0x1C,
|
||||
ANSI_0 = 0x1D,
|
||||
ANSI_RightBracket = 0x1E,
|
||||
ANSI_O = 0x1F,
|
||||
ANSI_U = 0x20,
|
||||
ANSI_LeftBracket = 0x21,
|
||||
ANSI_I = 0x22,
|
||||
ANSI_P = 0x23,
|
||||
ANSI_L = 0x25,
|
||||
ANSI_J = 0x26,
|
||||
ANSI_Quote = 0x27,
|
||||
ANSI_K = 0x28,
|
||||
ANSI_Semicolon = 0x29,
|
||||
ANSI_Backslash = 0x2A,
|
||||
ANSI_Comma = 0x2B,
|
||||
ANSI_Slash = 0x2C,
|
||||
ANSI_N = 0x2D,
|
||||
ANSI_M = 0x2E,
|
||||
ANSI_Period = 0x2F,
|
||||
ANSI_Grave = 0x32,
|
||||
ANSI_KeypadDecimal = 0x41,
|
||||
ANSI_KeypadMultiply = 0x43,
|
||||
ANSI_KeypadPlus = 0x45,
|
||||
ANSI_KeypadClear = 0x47,
|
||||
ANSI_KeypadDivide = 0x4B,
|
||||
ANSI_KeypadEnter = 0x4C,
|
||||
ANSI_KeypadMinus = 0x4E,
|
||||
ANSI_KeypadEquals = 0x51,
|
||||
ANSI_Keypad0 = 0x52,
|
||||
ANSI_Keypad1 = 0x53,
|
||||
ANSI_Keypad2 = 0x54,
|
||||
ANSI_Keypad3 = 0x55,
|
||||
ANSI_Keypad4 = 0x56,
|
||||
ANSI_Keypad5 = 0x57,
|
||||
ANSI_Keypad6 = 0x58,
|
||||
ANSI_Keypad7 = 0x59,
|
||||
ANSI_Keypad8 = 0x5B,
|
||||
ANSI_Keypad9 = 0x5C,
|
||||
Return = 0x24,
|
||||
Tab = 0x30,
|
||||
Space = 0x31,
|
||||
Delete = 0x33,
|
||||
Escape = 0x35,
|
||||
Command = 0x37,
|
||||
Shift = 0x38,
|
||||
CapsLock = 0x39,
|
||||
Option = 0x3A,
|
||||
Control = 0x3B,
|
||||
RightCommand = 0x36,
|
||||
RightShift = 0x3C,
|
||||
RightOption = 0x3D,
|
||||
RightControl = 0x3E,
|
||||
Function = 0x3F,
|
||||
F17 = 0x40,
|
||||
VolumeUp = 0x48,
|
||||
VolumeDown = 0x49,
|
||||
Mute = 0x4A,
|
||||
F18 = 0x4F,
|
||||
F19 = 0x50,
|
||||
F20 = 0x5A,
|
||||
F5 = 0x60,
|
||||
F6 = 0x61,
|
||||
F7 = 0x62,
|
||||
F3 = 0x63,
|
||||
F8 = 0x64,
|
||||
F9 = 0x65,
|
||||
F11 = 0x67,
|
||||
F13 = 0x69,
|
||||
F16 = 0x6A,
|
||||
F14 = 0x6B,
|
||||
F10 = 0x6D,
|
||||
F12 = 0x6F,
|
||||
F15 = 0x71,
|
||||
Help = 0x72,
|
||||
Home = 0x73,
|
||||
PageUp = 0x74,
|
||||
ForwardDelete = 0x75,
|
||||
F4 = 0x76,
|
||||
End = 0x77,
|
||||
F2 = 0x78,
|
||||
PageDown = 0x79,
|
||||
F1 = 0x7A,
|
||||
LeftArrow = 0x7B,
|
||||
RightArrow = 0x7C,
|
||||
DownArrow = 0x7D,
|
||||
UpArrow = 0x7E,
|
||||
JIS_Yen = 0x5D,
|
||||
JIS_Underscore = 0x5E,
|
||||
JIS_KeypadComma = 0x5F,
|
||||
JIS_Eisu = 0x66,
|
||||
JIS_Kana = 0x68,
|
||||
ISO_Section = 0x0A,
|
||||
}
|
||||
|
||||
|
||||
/* these messages are valid for all events */
|
||||
|
||||
@(objc_type=Event, objc_name="type")
|
||||
Event_type :: proc "c" (self: ^Event) -> EventType {
|
||||
return msgSend(EventType, self, "type")
|
||||
}
|
||||
@(objc_type=Event, objc_name="modifierFlags")
|
||||
Event_modifierFlags :: proc "c" (self: ^Event) -> UInteger {
|
||||
return msgSend(UInteger, self, "modifierFlags")
|
||||
}
|
||||
@(objc_type=Event, objc_name="timestamp")
|
||||
Event_timestamp :: proc "c" (self: ^Event) -> TimeInterval {
|
||||
return msgSend(TimeInterval, self, "timestamp")
|
||||
}
|
||||
@(objc_type=Event, objc_name="window")
|
||||
Event_window :: proc "c" (self: ^Event) -> ^Window {
|
||||
return msgSend(^Window, self, "window")
|
||||
}
|
||||
@(objc_type=Event, objc_name="windowNumber")
|
||||
Event_windowNumber :: proc "c" (self: ^Event) -> UInteger {
|
||||
return msgSend(UInteger, self, "windowNumber")
|
||||
}
|
||||
|
||||
/* these messages are valid for all mouse down/up/drag events */
|
||||
|
||||
@(objc_type=Event, objc_name="clickCount")
|
||||
Event_clickCount :: proc "c" (self: ^Event) -> Integer {
|
||||
return msgSend(Integer, self, "clickCount")
|
||||
}
|
||||
|
||||
// for NSOtherMouse events, but will return valid constants for NSLeftMouse and NSRightMouse
|
||||
@(objc_type=Event, objc_name="buttonNumber")
|
||||
Event_buttonNumber :: proc "c" (self: ^Event) -> Integer {
|
||||
return msgSend(Integer, self, "buttonNumber")
|
||||
}
|
||||
|
||||
/* these messages are valid for all mouse down/up/drag and enter/exit events */
|
||||
@(objc_type=Event, objc_name="eventNumber")
|
||||
Event_eventNumber :: proc "c" (self: ^Event) -> Integer {
|
||||
return msgSend(Integer, self, "eventNumber")
|
||||
}
|
||||
|
||||
/* -pressure is valid for all mouse down/up/drag events, and is also valid for NSTabletPoint events on 10.4 or later */
|
||||
@(objc_type=Event, objc_name="pressure")
|
||||
Event_pressure :: proc "c" (self: ^Event) -> f32 {
|
||||
return msgSend(f32, self, "pressure")
|
||||
}
|
||||
|
||||
/* -locationInWindow is valid for all mouse-related events */
|
||||
@(objc_type=Event, objc_name="locationInWindow")
|
||||
Event_locationInWindow :: proc "c" (self: ^Event) -> Point {
|
||||
return msgSend(Point, self, "locationInWindow")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Event, objc_name="deltaX")
|
||||
Event_deltaX :: proc "c" (self: ^Event) -> Float {
|
||||
return msgSend(Float, self, "deltaX")
|
||||
}
|
||||
@(objc_type=Event, objc_name="deltaY")
|
||||
Event_deltaY :: proc "c" (self: ^Event) -> Float {
|
||||
return msgSend(Float, self, "deltaY")
|
||||
}
|
||||
@(objc_type=Event, objc_name="deltaZ")
|
||||
Event_deltaZ :: proc "c" (self: ^Event) -> Float {
|
||||
return msgSend(Float, self, "deltaZ")
|
||||
}
|
||||
@(objc_type=Event, objc_name="delta")
|
||||
Event_delta :: proc "c" (self: ^Event) -> (x, y, z: Float) {
|
||||
x = self->deltaX()
|
||||
y = self->deltaY()
|
||||
z = self->deltaZ()
|
||||
return
|
||||
}
|
||||
|
||||
@(objc_type=Event, objc_name="hasPreciseScrollingDeltas")
|
||||
Event_hasPreciseScrollingDeltas :: proc "c" (self: ^Event) -> BOOL {
|
||||
return msgSend(BOOL, self, "hasPreciseScrollingDeltas")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Event, objc_name="scrollingDeltaX")
|
||||
Event_scrollingDeltaX :: proc "c" (self: ^Event) -> Float {
|
||||
return msgSend(Float, self, "scrollingDeltaX")
|
||||
}
|
||||
@(objc_type=Event, objc_name="scrollingDeltaY")
|
||||
Event_scrollingDeltaY :: proc "c" (self: ^Event) -> Float {
|
||||
return msgSend(Float, self, "scrollingDeltaY")
|
||||
}
|
||||
@(objc_type=Event, objc_name="scrollingDelta")
|
||||
Event_scrollingDelta :: proc "c" (self: ^Event) -> (x, y: Float) {
|
||||
x = self->scrollingDeltaX()
|
||||
y = self->scrollingDeltaY()
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(objc_type=Event, objc_name="momentumPhase")
|
||||
Event_momentumPhase :: proc "c" (self: ^Event) -> EventPhase {
|
||||
return msgSend(EventPhase, self, "momentumPhase")
|
||||
}
|
||||
@(objc_type=Event, objc_name="phase")
|
||||
Event_phase :: proc "c" (self: ^Event) -> EventPhase {
|
||||
return msgSend(EventPhase, self, "phase")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Event, objc_name="isDirectionInvertedFromDevice")
|
||||
Event_isDirectionInvertedFromDevice :: proc "c" (self: ^Event) -> BOOL {
|
||||
return msgSend(BOOL, self, "isDirectionInvertedFromDevice")
|
||||
}
|
||||
|
||||
@(objc_type=Event, objc_name="characters")
|
||||
Event_characters :: proc "c" (self: ^Event) -> ^String {
|
||||
return msgSend(^String, self, "characters")
|
||||
}
|
||||
@(objc_type=Event, objc_name="charactersIgnoringModifiers")
|
||||
Event_charactersIgnoringModifiers :: proc "c" (self: ^Event) -> ^String {
|
||||
return msgSend(^String, self, "charactersIgnoringModifiers")
|
||||
}
|
||||
@(objc_type=Event, objc_name="isARepeat")
|
||||
Event_isARepeat :: proc "c" (self: ^Event) -> BOOL {
|
||||
return msgSend(BOOL, self, "isARepeat")
|
||||
}
|
||||
|
||||
@(objc_type=Event, objc_name="keyCode")
|
||||
Event_keyCode :: proc "c" (self: ^Event) -> u16 {
|
||||
return msgSend(u16, self, "keyCode")
|
||||
}
|
||||
|
||||
@(objc_type=Event, objc_name="subtype")
|
||||
Event_subtype :: proc "c" (self: ^Event) -> i16 {
|
||||
return msgSend(i16, self, "subtype")
|
||||
}
|
||||
|
||||
@(objc_type=Event, objc_name="data1")
|
||||
Event_data1 :: proc "c" (self: ^Event) -> Integer {
|
||||
return msgSend(Integer, self, "data1")
|
||||
}
|
||||
@(objc_type=Event, objc_name="data2")
|
||||
Event_data2 :: proc "c" (self: ^Event) -> Integer {
|
||||
return msgSend(Integer, self, "data2")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Event, objc_name="absoluteX")
|
||||
Event_absoluteX :: proc "c" (self: ^Event) -> Integer {
|
||||
return msgSend(Integer, self, "absoluteX")
|
||||
}
|
||||
@(objc_type=Event, objc_name="absoluteY")
|
||||
Event_absoluteY :: proc "c" (self: ^Event) -> Integer {
|
||||
return msgSend(Integer, self, "absoluteY")
|
||||
}
|
||||
@(objc_type=Event, objc_name="absoluteZ")
|
||||
Event_absoluteZ :: proc "c" (self: ^Event) -> Integer {
|
||||
return msgSend(Integer, self, "absoluteZ")
|
||||
}
|
||||
|
||||
@(objc_type=Event, objc_name="absolute")
|
||||
Event_absolute :: proc "c" (self: ^Event) -> (x, y, z: Integer) {
|
||||
x = self->absoluteX()
|
||||
y = self->absoluteY()
|
||||
z = self->absoluteZ()
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Event, objc_name="buttonMask")
|
||||
Event_buttonMask :: proc "c" (self: ^Event) -> UInteger {
|
||||
return msgSend(UInteger, self, "buttonMask")
|
||||
}
|
||||
|
||||
@(objc_type=Event, objc_name="tilt")
|
||||
tilt :: proc "c" (self: ^Event) -> Point {
|
||||
return msgSend(Point, self, "tilt")
|
||||
}
|
||||
|
||||
@(objc_type=Event, objc_name="tangentialPressure")
|
||||
Event_tangentialPressure :: proc "c" (self: ^Event) -> f32 {
|
||||
return msgSend(f32, self, "tangentialPressure")
|
||||
}
|
||||
|
||||
@(objc_type=Event, objc_name="vendorDefined")
|
||||
Event_vendorDefined :: proc "c" (self: ^Event) -> id {
|
||||
return msgSend(id, self, "vendorDefined")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Event, objc_name="vendorID")
|
||||
Event_vendorID :: proc "c" (self: ^Event) -> UInteger {
|
||||
return msgSend(UInteger, self, "vendorID")
|
||||
}
|
||||
@(objc_type=Event, objc_name="tabletID")
|
||||
Event_tabletID :: proc "c" (self: ^Event) -> UInteger {
|
||||
return msgSend(UInteger, self, "tabletID")
|
||||
}
|
||||
@(objc_type=Event, objc_name="pointingDeviceID")
|
||||
Event_pointingDeviceID :: proc "c" (self: ^Event) -> UInteger {
|
||||
return msgSend(UInteger, self, "pointingDeviceID")
|
||||
}
|
||||
@(objc_type=Event, objc_name="systemTabletID")
|
||||
Event_systemTabletID :: proc "c" (self: ^Event) -> UInteger {
|
||||
return msgSend(UInteger, self, "systemTabletID")
|
||||
}
|
||||
@(objc_type=Event, objc_name="vendorPointingDeviceType")
|
||||
Event_vendorPointingDeviceType :: proc "c" (self: ^Event) -> UInteger {
|
||||
return msgSend(UInteger, self, "vendorPointingDeviceType")
|
||||
}
|
||||
@(objc_type=Event, objc_name="pointingDeviceSerialNumber")
|
||||
Event_pointingDeviceSerialNumber :: proc "c" (self: ^Event) -> UInteger {
|
||||
return msgSend(UInteger, self, "pointingDeviceSerialNumber")
|
||||
}
|
||||
@(objc_type=Event, objc_name="uniqueID")
|
||||
Event_uniqueID :: proc "c" (self: ^Event) -> u64 {
|
||||
return msgSend(u64, self, "uniqueID")
|
||||
}
|
||||
@(objc_type=Event, objc_name="capabilityMask")
|
||||
Event_capabilityMask :: proc "c" (self: ^Event) -> UInteger {
|
||||
return msgSend(UInteger, self, "capabilityMask")
|
||||
}
|
||||
@(objc_type=Event, objc_name="pointingDeviceType")
|
||||
Event_pointingDeviceType :: proc "c" (self: ^Event) -> PointingDeviceType {
|
||||
return msgSend(PointingDeviceType, self, "pointingDeviceType")
|
||||
}
|
||||
@(objc_type=Event, objc_name="isEnteringProximity")
|
||||
Event_isEnteringProximity :: proc "c" (self: ^Event) -> BOOL {
|
||||
return msgSend(BOOL, self, "isEnteringProximity")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Event, objc_name="isSwipeTrackingFromScrollEventsEnabled")
|
||||
Event_isSwipeTrackingFromScrollEventsEnabled :: proc "c" (self: ^Event) -> BOOL {
|
||||
return msgSend(BOOL, self, "isSwipeTrackingFromScrollEventsEnabled")
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package objc_Foundation
|
||||
|
||||
Locking :: struct($T: typeid) {using _: Object}
|
||||
|
||||
Locking_lock :: proc "c" (self: ^Locking($T)) {
|
||||
msgSend(nil, self, "lock")
|
||||
}
|
||||
Locking_unlock :: proc "c" (self: ^Locking($T)) {
|
||||
msgSend(nil, self, "unlock")
|
||||
}
|
||||
|
||||
@(objc_class="NSCondition")
|
||||
Condition :: struct {using _: Locking(Condition) }
|
||||
|
||||
|
||||
@(objc_type=Condition, objc_name="alloc", objc_is_class_method=true)
|
||||
Condition_alloc :: proc "c" () -> ^Condition {
|
||||
return msgSend(^Condition, Condition, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="init")
|
||||
Condition_init :: proc "c" (self: ^Condition) -> ^Condition {
|
||||
return msgSend(^Condition, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="wait")
|
||||
Condition_wait :: proc "c" (self: ^Condition) {
|
||||
msgSend(nil, self, "wait")
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="waitUntilDate")
|
||||
Condition_waitUntilDate :: proc "c" (self: ^Condition, limit: ^Date) -> BOOL {
|
||||
return msgSend(BOOL, self, "waitUntilDate:", limit)
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="signal")
|
||||
Condition_signal :: proc "c" (self: ^Condition) {
|
||||
msgSend(nil, self, "signal")
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="broadcast")
|
||||
Condition_broadcast :: proc "c" (self: ^Condition) {
|
||||
msgSend(nil, self, "broadcast")
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="lock")
|
||||
Condition_lock :: proc "c" (self: ^Condition) {
|
||||
msgSend(nil, self, "lock")
|
||||
}
|
||||
@(objc_type=Condition, objc_name="unlock")
|
||||
Condition_unlock :: proc "c" (self: ^Condition) {
|
||||
msgSend(nil, self, "unlock")
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package objc_Foundation
|
||||
|
||||
import "base:builtin"
|
||||
import "base:intrinsics"
|
||||
|
||||
KeyEquivalentModifierFlag :: enum UInteger {
|
||||
CapsLock = 16, // Set if Caps Lock key is pressed.
|
||||
Shift = 17, // Set if Shift key is pressed.
|
||||
Control = 18, // Set if Control key is pressed.
|
||||
Option = 19, // Set if Option or Alternate key is pressed.
|
||||
Command = 20, // Set if Command key is pressed.
|
||||
NumericPad = 21, // Set if any key in the numeric keypad is pressed.
|
||||
Help = 22, // Set if the Help key is pressed.
|
||||
Function = 23, // Set if any function key is pressed.
|
||||
}
|
||||
KeyEquivalentModifierMask :: distinct bit_set[KeyEquivalentModifierFlag; UInteger]
|
||||
|
||||
// Used to retrieve only the device-independent modifier flags, allowing applications to mask off the device-dependent modifier flags, including event coalescing information.
|
||||
KeyEventModifierFlagDeviceIndependentFlagsMask := transmute(KeyEquivalentModifierMask)_KeyEventModifierFlagDeviceIndependentFlagsMask
|
||||
@(private) _KeyEventModifierFlagDeviceIndependentFlagsMask := UInteger(0xffff0000)
|
||||
|
||||
|
||||
MenuItemCallback :: proc "c" (unused: rawptr, name: SEL, sender: ^Object)
|
||||
|
||||
|
||||
@(objc_class="NSMenuItem")
|
||||
MenuItem :: struct {using _: Object}
|
||||
|
||||
@(objc_type=MenuItem, objc_name="alloc", objc_is_class_method=true)
|
||||
MenuItem_alloc :: proc "c" () -> ^MenuItem {
|
||||
return msgSend(^MenuItem, MenuItem, "alloc")
|
||||
}
|
||||
@(objc_type=MenuItem, objc_name="registerActionCallback", objc_is_class_method=true)
|
||||
MenuItem_registerActionCallback :: proc "c" (name: cstring, callback: MenuItemCallback) -> SEL {
|
||||
s := string(name)
|
||||
n := len(s)
|
||||
sel: SEL
|
||||
if n > 0 && s[n-1] != ':' {
|
||||
col_name := intrinsics.alloca(n+2, 1)
|
||||
builtin.copy(col_name[:n], s)
|
||||
col_name[n] = ':'
|
||||
col_name[n+1] = 0
|
||||
sel = sel_registerName(cstring(col_name))
|
||||
} else {
|
||||
sel = sel_registerName(name)
|
||||
}
|
||||
if callback != nil {
|
||||
class_addMethod(intrinsics.objc_find_class("NSObject"), sel, auto_cast callback, "v@:@")
|
||||
}
|
||||
return sel
|
||||
}
|
||||
|
||||
@(objc_type=MenuItem, objc_name="init")
|
||||
MenuItem_init :: proc "c" (self: ^MenuItem) -> ^MenuItem {
|
||||
return msgSend(^MenuItem, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=MenuItem, objc_name="setKeyEquivalentModifierMask")
|
||||
MenuItem_setKeyEquivalentModifierMask :: proc "c" (self: ^MenuItem, modifierMask: KeyEquivalentModifierMask) {
|
||||
msgSend(nil, self, "setKeyEquivalentModifierMask:", modifierMask)
|
||||
}
|
||||
|
||||
@(objc_type=MenuItem, objc_name="keyEquivalentModifierMask")
|
||||
MenuItem_keyEquivalentModifierMask :: proc "c" (self: ^MenuItem) -> KeyEquivalentModifierMask {
|
||||
return msgSend(KeyEquivalentModifierMask, self, "keyEquivalentModifierMask")
|
||||
}
|
||||
|
||||
@(objc_type=MenuItem, objc_name="setSubmenu")
|
||||
MenuItem_setSubmenu :: proc "c" (self: ^MenuItem, submenu: ^Menu) {
|
||||
msgSend(nil, self, "setSubmenu:", submenu)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@(objc_class="NSMenu")
|
||||
Menu :: struct {using _: Object}
|
||||
|
||||
@(objc_type=Menu, objc_name="alloc", objc_is_class_method=true)
|
||||
Menu_alloc :: proc "c" () -> ^Menu {
|
||||
return msgSend(^Menu, Menu, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Menu, objc_name="init")
|
||||
Menu_init :: proc "c" (self: ^Menu) -> ^Menu {
|
||||
return msgSend(^Menu, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Menu, objc_name="initWithTitle")
|
||||
Menu_initWithTitle :: proc "c" (self: ^Menu, title: ^String) -> ^Menu {
|
||||
return msgSend(^Menu, self, "initWithTitle:", title)
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Menu, objc_name="addItem")
|
||||
Menu_addItem :: proc "c" (self: ^Menu, item: ^MenuItem) {
|
||||
msgSend(nil, self, "addItem:", item)
|
||||
}
|
||||
|
||||
@(objc_type=Menu, objc_name="addItemWithTitle")
|
||||
Menu_addItemWithTitle :: proc "c" (self: ^Menu, title: ^String, selector: SEL, keyEquivalent: ^String) -> ^MenuItem {
|
||||
return msgSend(^MenuItem, self, "addItemWithTitle:action:keyEquivalent:", title, selector, keyEquivalent)
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSNotification")
|
||||
Notification :: struct{using _: Object}
|
||||
|
||||
|
||||
@(objc_type=Notification, objc_name="alloc", objc_is_class_method=true)
|
||||
Notification_alloc :: proc "c" () -> ^Notification {
|
||||
return msgSend(^Notification, Notification, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Notification, objc_name="init")
|
||||
Notification_init :: proc "c" (self: ^Notification) -> ^Notification {
|
||||
return msgSend(^Notification, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Notification, objc_name="name")
|
||||
Notification_name :: proc "c" (self: ^Notification) -> ^String {
|
||||
return msgSend(^String, self, "name")
|
||||
}
|
||||
|
||||
@(objc_type=Notification, objc_name="object")
|
||||
Notification_object :: proc "c" (self: ^Notification) -> ^Object {
|
||||
return msgSend(^Object, self, "object")
|
||||
}
|
||||
|
||||
@(objc_type=Notification, objc_name="userInfo")
|
||||
Notification_userInfo :: proc "c" (self: ^Notification) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "userInfo")
|
||||
}
|
||||
|
||||
NotificationName :: ^String
|
||||
|
||||
@(objc_class="NSNotificationCenter")
|
||||
NotificationCenter :: struct{using _: Object}
|
||||
|
||||
|
||||
@(objc_type=NotificationCenter, objc_name="alloc", objc_is_class_method=true)
|
||||
NotificationCenter_alloc :: proc "c" () -> ^NotificationCenter {
|
||||
return msgSend(^NotificationCenter, NotificationCenter, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=NotificationCenter, objc_name="init")
|
||||
NotificationCenter_init :: proc "c" (self: ^NotificationCenter) -> ^NotificationCenter {
|
||||
return msgSend(^NotificationCenter, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=NotificationCenter, objc_name="defaultCenter", objc_is_class_method=true)
|
||||
NotificationCenter_defaultCenter :: proc "c" () -> ^NotificationCenter {
|
||||
return msgSend(^NotificationCenter, NotificationCenter, "defaultCenter")
|
||||
}
|
||||
|
||||
@(objc_type=NotificationCenter, objc_name="addObserver")
|
||||
NotificationCenter_addObserverName :: proc "c" (self: ^NotificationCenter, name: NotificationName, pObj: ^Object, pQueue: rawptr, block: ^Block) -> ^Object {
|
||||
return msgSend(^Object, self, "addObserverName:object:queue:block:", name, pObj, pQueue, block)
|
||||
}
|
||||
@(objc_type=NotificationCenter, objc_name="removeObserver")
|
||||
NotificationCenter_removeObserver :: proc "c" (self: ^NotificationCenter, pObserver: ^Object) {
|
||||
msgSend(nil, self, "removeObserver:", pObserver)
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package objc_Foundation
|
||||
|
||||
import "core:c"
|
||||
_ :: c
|
||||
when ODIN_OS == .Darwin {
|
||||
#assert(size_of(c.long) == size_of(int))
|
||||
#assert(size_of(c.ulong) == size_of(uint))
|
||||
}
|
||||
|
||||
@(objc_class="NSValue")
|
||||
Value :: struct{using _: Copying(Value)}
|
||||
|
||||
@(objc_type=Value, objc_name="alloc", objc_is_class_method=true)
|
||||
Value_alloc :: proc "c" () -> ^Value {
|
||||
return msgSend(^Value, Value, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="init")
|
||||
Value_init :: proc "c" (self: ^Value) -> ^Value {
|
||||
return msgSend(^Value, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="valueWithBytes", objc_is_class_method=true)
|
||||
Value_valueWithBytes :: proc "c" (value: rawptr, type: cstring) -> ^Value {
|
||||
return msgSend(^Value, Value, "valueWithBytes:objCType:", value, type)
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="valueWithPointer", objc_is_class_method=true)
|
||||
Value_valueWithPointer :: proc "c" (pointer: rawptr) -> ^Value {
|
||||
return msgSend(^Value, Value, "valueWithPointer:", pointer)
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="initWithBytes")
|
||||
Value_initWithBytes :: proc "c" (self: ^Value, value: rawptr, type: cstring) -> ^Value {
|
||||
return msgSend(^Value, self, "initWithBytes:objCType:", value, type)
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="initWithCoder")
|
||||
Value_initWithCoder :: proc "c" (self: ^Value, coder: ^Coder) -> ^Value {
|
||||
return msgSend(^Value, self, "initWithCoder:", coder)
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="getValue")
|
||||
Value_getValue :: proc "c" (self: ^Value, value: rawptr, size: UInteger) {
|
||||
msgSend(nil, self, "getValue:size:", value, size)
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Value, objc_name="objCType")
|
||||
Value_objCType :: proc "c" (self: ^Value) -> cstring {
|
||||
return msgSend(cstring, self, "objCType")
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="isEqualToValue")
|
||||
Value_isEqualToValue :: proc "c" (self, other: ^Value) -> BOOL {
|
||||
return msgSend(BOOL, self, "isEqualToValue:", other)
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="pointerValue")
|
||||
Value_pointerValue :: proc "c" (self: ^Value) -> rawptr {
|
||||
return msgSend(rawptr, self, "pointerValue")
|
||||
}
|
||||
|
||||
|
||||
@(objc_class="NSNumber")
|
||||
Number :: struct{using _: Copying(Number), using _: Value}
|
||||
|
||||
@(objc_type=Number, objc_name="alloc", objc_is_class_method=true)
|
||||
Number_alloc :: proc "c" () -> ^Number {
|
||||
return msgSend(^Number, Number, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Number, objc_name="init")
|
||||
Number_init :: proc "c" (self: ^Number) -> ^Number {
|
||||
return msgSend(^Number, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Number, objc_name="numberWithI8", objc_is_class_method=true) Number_numberWithI8 :: proc "c" (value: i8) -> ^Number { return msgSend(^Number, Number, "numberWithChar:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithU8", objc_is_class_method=true) Number_numberWithU8 :: proc "c" (value: u8) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedChar:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithI16", objc_is_class_method=true) Number_numberWithI16 :: proc "c" (value: i16) -> ^Number { return msgSend(^Number, Number, "numberWithShort:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithU16", objc_is_class_method=true) Number_numberWithU16 :: proc "c" (value: u16) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedShort:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithI32", objc_is_class_method=true) Number_numberWithI32 :: proc "c" (value: i32) -> ^Number { return msgSend(^Number, Number, "numberWithInt:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithU32", objc_is_class_method=true) Number_numberWithU32 :: proc "c" (value: u32) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedInt:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithInt", objc_is_class_method=true) Number_numberWithInt :: proc "c" (value: int) -> ^Number { return msgSend(^Number, Number, "numberWithLong:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithUint", objc_is_class_method=true) Number_numberWithUint :: proc "c" (value: uint) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLong:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithU64", objc_is_class_method=true) Number_numberWithU64 :: proc "c" (value: u64) -> ^Number { return msgSend(^Number, Number, "numberWithLongLong:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithI64", objc_is_class_method=true) Number_numberWithI64 :: proc "c" (value: i64) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLongLong:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithF32", objc_is_class_method=true) Number_numberWithF32 :: proc "c" (value: f32) -> ^Number { return msgSend(^Number, Number, "numberWithFloat:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithF64", objc_is_class_method=true) Number_numberWithF64 :: proc "c" (value: f64) -> ^Number { return msgSend(^Number, Number, "numberWithDouble:", value) }
|
||||
@(objc_type=Number, objc_name="numberWithBool", objc_is_class_method=true) Number_numberWithBool :: proc "c" (value: BOOL) -> ^Number { return msgSend(^Number, Number, "numberWithBool:", value) }
|
||||
|
||||
@(objc_type=Number, objc_name="number", objc_is_class_method=true)
|
||||
Number_number :: proc{
|
||||
Number_numberWithI8,
|
||||
Number_numberWithU8,
|
||||
Number_numberWithI16,
|
||||
Number_numberWithU16,
|
||||
Number_numberWithI32,
|
||||
Number_numberWithU32,
|
||||
Number_numberWithInt,
|
||||
Number_numberWithUint,
|
||||
Number_numberWithU64,
|
||||
Number_numberWithI64,
|
||||
Number_numberWithF32,
|
||||
Number_numberWithF64,
|
||||
Number_numberWithBool,
|
||||
}
|
||||
|
||||
@(objc_type=Number, objc_name="initWithI8") Number_initWithI8 :: proc "c" (self: ^Number, value: i8) -> ^Number { return msgSend(^Number, self, "initWithChar:", value) }
|
||||
@(objc_type=Number, objc_name="initWithU8") Number_initWithU8 :: proc "c" (self: ^Number, value: u8) -> ^Number { return msgSend(^Number, self, "initWithUnsignedChar:", value) }
|
||||
@(objc_type=Number, objc_name="initWithI16") Number_initWithI16 :: proc "c" (self: ^Number, value: i16) -> ^Number { return msgSend(^Number, self, "initWithShort:", value) }
|
||||
@(objc_type=Number, objc_name="initWithU16") Number_initWithU16 :: proc "c" (self: ^Number, value: u16) -> ^Number { return msgSend(^Number, self, "initWithUnsignedShort:", value) }
|
||||
@(objc_type=Number, objc_name="initWithI32") Number_initWithI32 :: proc "c" (self: ^Number, value: i32) -> ^Number { return msgSend(^Number, self, "initWithInt:", value) }
|
||||
@(objc_type=Number, objc_name="initWithU32") Number_initWithU32 :: proc "c" (self: ^Number, value: u32) -> ^Number { return msgSend(^Number, self, "initWithUnsignedInt:", value) }
|
||||
@(objc_type=Number, objc_name="initWithInt") Number_initWithInt :: proc "c" (self: ^Number, value: int) -> ^Number { return msgSend(^Number, self, "initWithLong:", value) }
|
||||
@(objc_type=Number, objc_name="initWithUint") Number_initWithUint :: proc "c" (self: ^Number, value: uint) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLong:", value) }
|
||||
@(objc_type=Number, objc_name="initWithU64") Number_initWithU64 :: proc "c" (self: ^Number, value: u64) -> ^Number { return msgSend(^Number, self, "initWithLongLong:", value) }
|
||||
@(objc_type=Number, objc_name="initWithI64") Number_initWithI64 :: proc "c" (self: ^Number, value: i64) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLongLong:", value) }
|
||||
@(objc_type=Number, objc_name="initWithF32") Number_initWithF32 :: proc "c" (self: ^Number, value: f32) -> ^Number { return msgSend(^Number, self, "initWithFloat:", value) }
|
||||
@(objc_type=Number, objc_name="initWithF64") Number_initWithF64 :: proc "c" (self: ^Number, value: f64) -> ^Number { return msgSend(^Number, self, "initWithDouble:", value) }
|
||||
@(objc_type=Number, objc_name="initWithBool") Number_initWithBool :: proc "c" (self: ^Number, value: BOOL) -> ^Number { return msgSend(^Number, self, "initWithBool:", value) }
|
||||
|
||||
|
||||
@(objc_type=Number, objc_name="i8Value") Number_i8Value :: proc "c" (self: ^Number) -> i8 { return msgSend(i8, self, "charValue") }
|
||||
@(objc_type=Number, objc_name="u8Value") Number_u8Value :: proc "c" (self: ^Number) -> u8 { return msgSend(u8, self, "unsignedCharValue") }
|
||||
@(objc_type=Number, objc_name="i16Value") Number_i16Value :: proc "c" (self: ^Number) -> i16 { return msgSend(i16, self, "shortValue") }
|
||||
@(objc_type=Number, objc_name="u16Value") Number_u16Value :: proc "c" (self: ^Number) -> u16 { return msgSend(u16, self, "unsignedShortValue") }
|
||||
@(objc_type=Number, objc_name="i32Value") Number_i32Value :: proc "c" (self: ^Number) -> i32 { return msgSend(i32, self, "intValue") }
|
||||
@(objc_type=Number, objc_name="u32Value") Number_u32Value :: proc "c" (self: ^Number) -> u32 { return msgSend(u32, self, "unsignedIntValue") }
|
||||
@(objc_type=Number, objc_name="intValue") Number_intValue :: proc "c" (self: ^Number) -> int { return msgSend(int, self, "longValue") }
|
||||
@(objc_type=Number, objc_name="uintValue") Number_uintValue :: proc "c" (self: ^Number) -> uint { return msgSend(uint, self, "unsignedLongValue") }
|
||||
@(objc_type=Number, objc_name="u64Value") Number_u64Value :: proc "c" (self: ^Number) -> u64 { return msgSend(u64, self, "longLongValue") }
|
||||
@(objc_type=Number, objc_name="i64Value") Number_i64Value :: proc "c" (self: ^Number) -> i64 { return msgSend(i64, self, "unsignedLongLongValue") }
|
||||
@(objc_type=Number, objc_name="f32Value") Number_f32Value :: proc "c" (self: ^Number) -> f32 { return msgSend(f32, self, "floatValue") }
|
||||
@(objc_type=Number, objc_name="f64Value") Number_f64Value :: proc "c" (self: ^Number) -> f64 { return msgSend(f64, self, "doubleValue") }
|
||||
@(objc_type=Number, objc_name="boolValue") Number_boolValue :: proc "c" (self: ^Number) -> BOOL { return msgSend(BOOL, self, "boolValue") }
|
||||
@(objc_type=Number, objc_name="integerValue") Number_integerValue :: proc "c" (self: ^Number) -> Integer { return msgSend(Integer, self, "integerValue") }
|
||||
@(objc_type=Number, objc_name="uintegerValue") Number_uintegerValue :: proc "c" (self: ^Number) -> UInteger { return msgSend(UInteger, self, "unsignedIntegerValue") }
|
||||
@(objc_type=Number, objc_name="stringValue") Number_stringValue :: proc "c" (self: ^Number) -> ^String { return msgSend(^String, self, "stringValue") }
|
||||
|
||||
@(objc_type=Number, objc_name="compare")
|
||||
Number_compare :: proc "c" (self, other: ^Number) -> ComparisonResult {
|
||||
return msgSend(ComparisonResult, self, "compare:", other)
|
||||
}
|
||||
|
||||
@(objc_type=Number, objc_name="isEqualToNumber")
|
||||
Number_isEqualToNumber :: proc "c" (self, other: ^Number) -> BOOL {
|
||||
return msgSend(BOOL, self, "isEqualToNumber:", other)
|
||||
}
|
||||
|
||||
@(objc_type=Number, objc_name="descriptionWithLocale")
|
||||
Number_descriptionWithLocale :: proc "c" (self: ^Number, locale: ^Object) -> ^String {
|
||||
return msgSend(^String, self, "descriptionWithLocale:", locale)
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package objc_Foundation
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
methodSignatureForSelector :: proc "c" (obj: ^Object, selector: SEL) -> rawptr {
|
||||
return msgSend(rawptr, obj, "methodSignatureForSelector:", selector)
|
||||
}
|
||||
|
||||
respondsToSelector :: proc "c" (obj: ^Object, selector: SEL) -> BOOL {
|
||||
return msgSend(BOOL, obj, "respondsToSelector:", selector)
|
||||
}
|
||||
|
||||
msgSendSafeCheck :: proc "c" (obj: ^Object, selector: SEL) -> BOOL {
|
||||
return respondsToSelector(obj, selector) || methodSignatureForSelector(obj, selector) != nil
|
||||
}
|
||||
|
||||
|
||||
@(objc_class="NSObject")
|
||||
Object :: struct {using _: intrinsics.objc_object}
|
||||
|
||||
@(objc_class="NSObject")
|
||||
Copying :: struct($T: typeid) {using _: Object}
|
||||
|
||||
alloc :: proc "c" ($T: typeid) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
|
||||
return msgSend(^T, T, "alloc")
|
||||
}
|
||||
@(objc_type=Object, objc_name="init")
|
||||
init :: proc "c" (self: ^$T) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
|
||||
return msgSend(^T, self, "init")
|
||||
}
|
||||
@(objc_type=Object, objc_name="copy")
|
||||
copy :: proc "c" (self: ^Copying($T)) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
|
||||
return msgSend(^T, self, "copy")
|
||||
}
|
||||
|
||||
new :: proc "c" ($T: typeid) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
|
||||
return init(alloc(T))
|
||||
}
|
||||
|
||||
@(objc_type=Object, objc_name="retain")
|
||||
retain :: proc "c" (self: ^Object) {
|
||||
_ = msgSend(^Object, self, "retain")
|
||||
}
|
||||
@(objc_type=Object, objc_name="release")
|
||||
release :: proc "c" (self: ^Object) {
|
||||
msgSend(nil, self, "release")
|
||||
}
|
||||
@(objc_type=Object, objc_name="autorelease")
|
||||
autorelease :: proc "c" (self: ^Object) {
|
||||
msgSend(nil, self, "autorelease")
|
||||
}
|
||||
@(objc_type=Object, objc_name="retainCount")
|
||||
retainCount :: proc "c" (self: ^Object) -> UInteger {
|
||||
return msgSend(UInteger, self, "retainCount")
|
||||
}
|
||||
@(objc_type=Object, objc_name="class")
|
||||
class :: proc "c" (self: ^Object) -> Class {
|
||||
return msgSend(Class, self, "class")
|
||||
}
|
||||
|
||||
@(objc_type=Object, objc_name="hash")
|
||||
hash :: proc "c" (self: ^Object) -> UInteger {
|
||||
return msgSend(UInteger, self, "hash")
|
||||
}
|
||||
|
||||
@(objc_type=Object, objc_name="isEqual")
|
||||
isEqual :: proc "c" (self, pObject: ^Object) -> BOOL {
|
||||
return msgSend(BOOL, self, "isEqual:", pObject)
|
||||
}
|
||||
|
||||
@(objc_type=Object, objc_name="description")
|
||||
description :: proc "c" (self: ^Object) -> ^String {
|
||||
return msgSend(^String, self, "description")
|
||||
}
|
||||
|
||||
@(objc_type=Object, objc_name="debugDescription")
|
||||
debugDescription :: proc "c" (self: ^Object) -> ^String {
|
||||
if msgSendSafeCheck(self, intrinsics.objc_find_selector("debugDescription")) {
|
||||
return msgSend(^String, self, "debugDescription")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
bridgingCast :: proc "c" ($T: typeid, obj: ^Object) where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) {
|
||||
return (T)(obj)
|
||||
}
|
||||
|
||||
|
||||
@(objc_class="NSCoder")
|
||||
Coder :: struct {using _: Object}
|
||||
// TODO(bill): Implement all the methods for this massive type
|
||||
@@ -0,0 +1,31 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSOpenPanel")
|
||||
OpenPanel :: struct{ using _: SavePanel }
|
||||
|
||||
@(objc_type=OpenPanel, objc_name="openPanel", objc_is_class_method=true)
|
||||
OpenPanel_openPanel :: proc "c" () -> ^OpenPanel {
|
||||
return msgSend(^OpenPanel, OpenPanel, "openPanel")
|
||||
}
|
||||
|
||||
@(objc_type=OpenPanel, objc_name="URLs")
|
||||
OpenPanel_URLs :: proc "c" (self: ^OpenPanel) -> ^Array {
|
||||
return msgSend(^Array, self, "URLs")
|
||||
}
|
||||
|
||||
@(objc_type=OpenPanel, objc_name="setCanChooseFiles")
|
||||
OpenPanel_setCanChooseFiles :: proc "c" (self: ^OpenPanel, setting: BOOL) {
|
||||
msgSend(nil, self, "setCanChooseFiles:", setting)
|
||||
}
|
||||
@(objc_type=OpenPanel, objc_name="setCanChooseDirectories")
|
||||
OpenPanel_setCanChooseDirectories :: proc "c" (self: ^OpenPanel, setting: BOOL) {
|
||||
msgSend(nil, self, "setCanChooseDirectories:", setting)
|
||||
}
|
||||
@(objc_type=OpenPanel, objc_name="setResolvesAliases")
|
||||
OpenPanel_setResolvesAliases :: proc "c" (self: ^OpenPanel, setting: BOOL) {
|
||||
msgSend(nil, self, "setResolvesAliases:", setting)
|
||||
}
|
||||
@(objc_type=OpenPanel, objc_name="setAllowsMultipleSelection")
|
||||
OpenPanel_setAllowsMultipleSelection :: proc "c" (self: ^OpenPanel, setting: BOOL) {
|
||||
msgSend(nil, self, "setAllowsMultipleSelection:", setting)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package objc_Foundation
|
||||
|
||||
ModalResponse :: enum UInteger {
|
||||
Cancel = 0,
|
||||
OK = 1,
|
||||
}
|
||||
|
||||
@(objc_class="NSPanel")
|
||||
Panel :: struct{ using _: Window }
|
||||
@@ -0,0 +1,5 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSPasteboard")
|
||||
Pasteboard :: struct {using _: Object}
|
||||
// TODO: implement NSPasteboard
|
||||
@@ -0,0 +1,22 @@
|
||||
package objc_Foundation
|
||||
|
||||
Range :: struct {
|
||||
location: UInteger,
|
||||
length: UInteger,
|
||||
}
|
||||
|
||||
Range_Make :: proc "c" (loc, len: UInteger) -> Range {
|
||||
return Range{loc, len}
|
||||
}
|
||||
|
||||
Range_Equal :: proc "c" (a, b: Range) -> BOOL {
|
||||
return a == b
|
||||
}
|
||||
|
||||
Range_LocationInRange :: proc "c" (self: Range, loc: UInteger) -> BOOL {
|
||||
return !((loc < self.location) && ((loc - self.location) < self.length))
|
||||
}
|
||||
|
||||
Range_Max :: proc "c" (self: Range) -> UInteger {
|
||||
return self.location + self.length
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSSavePanel")
|
||||
SavePanel :: struct{ using _: Panel }
|
||||
|
||||
@(objc_type=SavePanel, objc_name="runModal")
|
||||
SavePanel_runModal :: proc "c" (self: ^SavePanel) -> ModalResponse {
|
||||
return msgSend(ModalResponse, self, "runModal")
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSScreen")
|
||||
Screen :: struct {using _: Object}
|
||||
|
||||
@(objc_type=Screen, objc_name="mainScreen")
|
||||
Screen_mainScreen :: proc "c" () -> ^Screen {
|
||||
return msgSend(^Screen, Screen, "mainScreen")
|
||||
}
|
||||
@(objc_type=Screen, objc_name="deepestScreen")
|
||||
Screen_deepestScreen :: proc "c" () -> ^Screen {
|
||||
return msgSend(^Screen, Screen, "deepestScreen")
|
||||
}
|
||||
@(objc_type=Screen, objc_name="screens")
|
||||
Screen_screens :: proc "c" () -> ^Array {
|
||||
return msgSend(^Array, Screen, "screens")
|
||||
}
|
||||
@(objc_type=Screen, objc_name="frame")
|
||||
Screen_frame :: proc "c" (self: ^Screen) -> Rect {
|
||||
return msgSend(Rect, self, "frame")
|
||||
}
|
||||
@(objc_type=Screen, objc_name="depth")
|
||||
Screen_depth :: proc "c" (self: ^Screen) -> Depth {
|
||||
return msgSend(Depth, self, "depth")
|
||||
}
|
||||
@(objc_type=Screen, objc_name="visibleFrame")
|
||||
Screen_visibleFrame :: proc "c" (self: ^Screen) -> Rect {
|
||||
return msgSend(Rect, self, "visibleFrame")
|
||||
}
|
||||
@(objc_type=Screen, objc_name="colorSpace")
|
||||
Screen_colorSpace :: proc "c" (self: ^Screen) -> ^ColorSpace {
|
||||
return msgSend(^ColorSpace, self, "colorSpace")
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSSet")
|
||||
Set :: struct {using _: Copying(Set)}
|
||||
|
||||
|
||||
@(objc_type=Set, objc_name="alloc", objc_is_class_method=true)
|
||||
Set_alloc :: proc "c" () -> ^Set {
|
||||
return msgSend(^Set, Set, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Set, objc_name="init")
|
||||
Set_init :: proc "c" (self: ^Set) -> ^Set {
|
||||
return msgSend(^Set, self, "init")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Set, objc_name="initWithObjects")
|
||||
Set_initWithObjects :: proc "c" (self: ^Set, objects: [^]^Object, count: UInteger) -> ^Set {
|
||||
return msgSend(^Set, self, "initWithObjects:count:", objects, count)
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Set, objc_name="initWithCoder")
|
||||
Set_initWithCoder :: proc "c" (self: ^Set, coder: ^Coder) -> ^Set {
|
||||
return msgSend(^Set, self, "initWithCoder:", coder)
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package objc_Foundation
|
||||
|
||||
foreign import "system:Foundation.framework"
|
||||
|
||||
@(objc_class="NSString")
|
||||
String :: struct {using _: Copying(String)}
|
||||
|
||||
StringEncoding :: enum UInteger {
|
||||
ASCII = 1,
|
||||
NEXTSTEP = 2,
|
||||
JapaneseEUC = 3,
|
||||
UTF8 = 4,
|
||||
ISOLatin1 = 5,
|
||||
Symbol = 6,
|
||||
NonLossyASCII = 7,
|
||||
ShiftJIS = 8,
|
||||
ISOLatin2 = 9,
|
||||
Unicode = 10,
|
||||
WindowsCP1251 = 11,
|
||||
WindowsCP1252 = 12,
|
||||
WindowsCP1253 = 13,
|
||||
WindowsCP1254 = 14,
|
||||
WindowsCP1250 = 15,
|
||||
ISO2022JP = 21,
|
||||
MacOSRoman = 30,
|
||||
UTF16 = Unicode,
|
||||
UTF16BigEndian = 0x90000100,
|
||||
UTF16LittleEndian = 0x94000100,
|
||||
UTF32 = 0x8c000100,
|
||||
UTF32BigEndian = 0x98000100,
|
||||
UTF32LittleEndian = 0x9c000100,
|
||||
}
|
||||
|
||||
StringCompareOptions :: distinct bit_set[StringCompareOption; UInteger]
|
||||
StringCompareOption :: enum UInteger {
|
||||
CaseInsensitive = 0,
|
||||
LiteralSearch = 1,
|
||||
BackwardsSearch = 2,
|
||||
AnchoredSearch = 3,
|
||||
NumericSearch = 6,
|
||||
DiacriticInsensitive = 7,
|
||||
WidthInsensitive = 8,
|
||||
ForcedOrdering = 9,
|
||||
RegularExpression = 10,
|
||||
}
|
||||
|
||||
unichar :: distinct u16
|
||||
|
||||
AT :: MakeConstantString
|
||||
|
||||
// CFString is 'toll-free bridged' with its Cocoa Foundation counterpart, NSString.
|
||||
MakeConstantString :: proc "c" (#const c: cstring) -> ^String {
|
||||
foreign Foundation {
|
||||
__CFStringMakeConstantString :: proc "c" (c: cstring) -> ^String ---
|
||||
}
|
||||
return __CFStringMakeConstantString(c)
|
||||
}
|
||||
|
||||
@(link_prefix="NS", default_calling_convention="c")
|
||||
foreign Foundation {
|
||||
StringFromClass :: proc(cls: Class) -> ^String ---
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="alloc", objc_is_class_method=true)
|
||||
String_alloc :: proc "c" () -> ^String {
|
||||
return msgSend(^String, String, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="init")
|
||||
String_init :: proc "c" (self: ^String) -> ^String {
|
||||
return msgSend(^String, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="initWithString")
|
||||
String_initWithString :: proc "c" (self: ^String, other: ^String) -> ^String {
|
||||
return msgSend(^String, self, "initWithString:", other)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="initWithCString")
|
||||
String_initWithCString :: proc "c" (self: ^String, pString: cstring, encoding: StringEncoding) -> ^String {
|
||||
return msgSend(^String, self, "initWithCstring:encoding:", pString, encoding)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="initWithBytesNoCopy")
|
||||
String_initWithBytesNoCopy :: proc "c" (self: ^String, pBytes: rawptr, length: UInteger, encoding: StringEncoding, freeWhenDone: bool) -> ^String {
|
||||
return msgSend(^String, self, "initWithBytesNoCopy:length:encoding:freeWhenDone:", pBytes, length, encoding, freeWhenDone)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="initWithOdinString")
|
||||
String_initWithOdinString :: proc "c" (self: ^String, str: string) -> ^String {
|
||||
return String_initWithBytesNoCopy(self, raw_data(str), UInteger(len(str)), .UTF8, false)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="characterAtIndex")
|
||||
String_characterAtIndex :: proc "c" (self: ^String, index: UInteger) -> unichar {
|
||||
return msgSend(unichar, self, "characterAtIndex:", index)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="length")
|
||||
String_length :: proc "c" (self: ^String) -> UInteger {
|
||||
return msgSend(UInteger, self, "length")
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="cstringUsingEncoding")
|
||||
String_cstringUsingEncoding :: proc "c" (self: ^String, encoding: StringEncoding) -> cstring {
|
||||
return msgSend(cstring, self, "cStringUsingEncoding:", encoding)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="UTF8String")
|
||||
String_UTF8String :: proc "c" (self: ^String) -> cstring {
|
||||
return msgSend(cstring, self, "UTF8String")
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="odinString")
|
||||
String_odinString :: proc "c" (self: ^String) -> string {
|
||||
return string(String_UTF8String(self))
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="maximumLengthOfBytesUsingEncoding")
|
||||
String_maximumLengthOfBytesUsingEncoding :: proc "c" (self: ^String, encoding: StringEncoding) -> UInteger {
|
||||
return msgSend(UInteger, self, "maximumLengthOfBytesUsingEncoding:", encoding)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="lengthOfBytesUsingEncoding")
|
||||
String_lengthOfBytesUsingEncoding :: proc "c" (self: ^String, encoding: StringEncoding) -> UInteger {
|
||||
return msgSend(UInteger, self, "lengthOfBytesUsingEncoding:", encoding)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="isEqualToString")
|
||||
String_isEqualToString :: proc "c" (self, other: ^String) -> BOOL {
|
||||
return msgSend(BOOL, self, "isEqualToString:", other)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="rangeOfString")
|
||||
String_rangeOfString :: proc "c" (self, other: ^String, options: StringCompareOptions) -> Range {
|
||||
return msgSend(Range, self, "rangeOfString:options:", other, options)
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package objc_Foundation
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@(private) msgSend :: intrinsics.objc_send
|
||||
|
||||
id :: ^intrinsics.objc_object
|
||||
SEL :: ^intrinsics.objc_selector
|
||||
Class :: ^intrinsics.objc_class
|
||||
|
||||
TimeInterval :: distinct f64
|
||||
Integer :: distinct int
|
||||
UInteger :: distinct uint
|
||||
|
||||
IntegerMax :: max(Integer)
|
||||
Integermin :: min(Integer)
|
||||
UIntegerMax :: max(UInteger)
|
||||
|
||||
BOOL :: bool // TODO(bill): should this be `distinct`?
|
||||
YES :: true
|
||||
NO :: false
|
||||
|
||||
OperatingSystemVersion :: struct #packed {
|
||||
majorVersion: Integer,
|
||||
minorVersion: Integer,
|
||||
patchVersion: Integer,
|
||||
}
|
||||
|
||||
ComparisonResult :: enum Integer {
|
||||
OrderedAscending = -1,
|
||||
OrderedSame = 0,
|
||||
OrderedDescending = 1,
|
||||
}
|
||||
|
||||
NotFound :: IntegerMax
|
||||
|
||||
Float :: distinct (f32 when size_of(uint) == 4 else f64)
|
||||
|
||||
Point :: struct {
|
||||
x: Float,
|
||||
y: Float,
|
||||
}
|
||||
|
||||
Size :: struct {
|
||||
width: Float,
|
||||
height: Float,
|
||||
}
|
||||
|
||||
when size_of(UInteger) == 8 {
|
||||
_UINTEGER_ENCODING :: "Q"
|
||||
} else {
|
||||
_UINTEGER_ENCODING :: "I"
|
||||
}
|
||||
|
||||
when size_of(Float) == 8 {
|
||||
_POINT_ENCODING :: "{CGPoint=dd}"
|
||||
_SIZE_ENCODING :: "{CGSize=dd}"
|
||||
} else {
|
||||
_POINT_ENCODING :: "{NSPoint=ff}"
|
||||
_SIZE_ENCODING :: "{NSSize=ff}"
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSURL")
|
||||
URL :: struct{using _: Copying(URL)}
|
||||
|
||||
|
||||
@(objc_type=URL, objc_name="alloc", objc_is_class_method=true)
|
||||
URL_alloc :: proc "c" () -> ^URL {
|
||||
return msgSend(^URL, URL, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=URL, objc_name="init")
|
||||
URL_init :: proc "c" (self: ^URL) -> ^URL {
|
||||
return msgSend(^URL, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=URL, objc_name="initWithString")
|
||||
URL_initWithString :: proc "c" (self: ^URL, value: ^String) -> ^URL {
|
||||
return msgSend(^URL, self, "initWithString:", value)
|
||||
}
|
||||
|
||||
@(objc_type=URL, objc_name="initFileURLWithPath")
|
||||
URL_initFileURLWithPath :: proc "c" (self: ^URL, path: ^String) -> ^URL {
|
||||
return msgSend(^URL, self, "initFileURLWithPath:", path)
|
||||
}
|
||||
|
||||
@(objc_type=URL, objc_name="fileSystemRepresentation")
|
||||
URL_fileSystemRepresentation :: proc "c" (self: ^URL) -> cstring {
|
||||
return msgSend(cstring, self, "fileSystemRepresentation")
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSUndoManager")
|
||||
UndoManager :: struct {using _: Object}
|
||||
// TODO: implement NSUndoManager
|
||||
@@ -0,0 +1,5 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSUserActivity")
|
||||
UserActivity :: struct {using _: Object}
|
||||
// TODO: implement NSUserActivity
|
||||
@@ -0,0 +1,14 @@
|
||||
package objc_Foundation
|
||||
|
||||
@(objc_class="NSUserDefaults")
|
||||
UserDefaults :: struct { using _: Object }
|
||||
|
||||
@(objc_type=UserDefaults, objc_name="standardUserDefaults", objc_is_class_method=true)
|
||||
UserDefaults_standardUserDefaults :: proc "c" () -> ^UserDefaults {
|
||||
return msgSend(^UserDefaults, UserDefaults, "standardUserDefaults")
|
||||
}
|
||||
|
||||
@(objc_type=UserDefaults, objc_name="setBoolForKey")
|
||||
UserDefaults_setBoolForKey :: proc "c" (self: ^UserDefaults, value: BOOL, name: ^String) {
|
||||
msgSend(nil, self, "setBool:forKey:", value, name)
|
||||
}
|
||||
@@ -0,0 +1,714 @@
|
||||
package objc_Foundation
|
||||
|
||||
import "core:strings"
|
||||
import "base:runtime"
|
||||
import "base:intrinsics"
|
||||
|
||||
Rect :: struct {
|
||||
using origin: Point,
|
||||
using size: Size,
|
||||
}
|
||||
|
||||
Depth :: enum UInteger {
|
||||
onehundredtwentyeightBitRGB = 544,
|
||||
sixtyfourBitRGB = 528,
|
||||
twentyfourBitRGB = 520,
|
||||
}
|
||||
|
||||
when size_of(Float) == 8 {
|
||||
_RECT_ENCODING :: "{CGRect="+_POINT_ENCODING+_SIZE_ENCODING+"}"
|
||||
} else {
|
||||
_RECT_ENCODING :: "{NSRect="+_POINT_ENCODING+_SIZE_ENCODING+"}"
|
||||
}
|
||||
|
||||
WindowStyleFlag :: enum UInteger {
|
||||
Titled = 0,
|
||||
Closable = 1,
|
||||
Miniaturizable = 2,
|
||||
Resizable = 3,
|
||||
TexturedBackground = 8,
|
||||
UnifiedTitleAndToolbar = 12,
|
||||
FullScreen = 14,
|
||||
FullSizeContentView = 15,
|
||||
UtilityWindow = 4,
|
||||
DocModalWindow = 6,
|
||||
NonactivatingPanel = 7,
|
||||
HUDWindow = 13,
|
||||
}
|
||||
WindowStyleMask :: distinct bit_set[WindowStyleFlag; UInteger]
|
||||
WindowStyleMaskBorderless :: WindowStyleMask{}
|
||||
WindowStyleMaskTitled :: WindowStyleMask{.Titled}
|
||||
WindowStyleMaskClosable :: WindowStyleMask{.Closable}
|
||||
WindowStyleMaskMiniaturizable :: WindowStyleMask{.Miniaturizable}
|
||||
WindowStyleMaskResizable :: WindowStyleMask{.Resizable}
|
||||
WindowStyleMaskTexturedBackground :: WindowStyleMask{.TexturedBackground}
|
||||
WindowStyleMaskUnifiedTitleAndToolbar :: WindowStyleMask{.UnifiedTitleAndToolbar}
|
||||
WindowStyleMaskFullScreen :: WindowStyleMask{.FullScreen}
|
||||
WindowStyleMaskFullSizeContentView :: WindowStyleMask{.FullSizeContentView}
|
||||
WindowStyleMaskUtilityWindow :: WindowStyleMask{.UtilityWindow}
|
||||
WindowStyleMaskDocModalWindow :: WindowStyleMask{.DocModalWindow}
|
||||
WindowStyleMaskNonactivatingPanel :: WindowStyleMask{.NonactivatingPanel}
|
||||
WindowStyleMaskHUDWindow :: WindowStyleMask{.HUDWindow}
|
||||
|
||||
BackingStoreType :: enum UInteger {
|
||||
Retained = 0,
|
||||
Nonretained = 1,
|
||||
Buffered = 2,
|
||||
}
|
||||
|
||||
WindowDelegateTemplate :: struct {
|
||||
// Managing Sheets
|
||||
windowWillPositionSheetUsingRect: proc(window: ^Window, sheet: ^Window, rect: Rect) -> Rect,
|
||||
windowWillBeginSheet: proc(notification: ^Notification),
|
||||
windowDidEndSheet: proc(notification: ^Notification),
|
||||
// Sizing Windows
|
||||
windowWillResizeToSize: proc(sender: ^Window, frameSize: Size) -> Size,
|
||||
windowDidResize: proc(notification: ^Notification),
|
||||
windowWillStartLiveResize: proc(noitifcation: ^Notification),
|
||||
windowDidEndLiveResize: proc(notification: ^Notification),
|
||||
// Minimizing Windows
|
||||
windowWillMiniaturize: proc(notification: ^Notification),
|
||||
windowDidMiniaturize: proc(notification: ^Notification),
|
||||
windowDidDeminiaturize: proc(notification: ^Notification),
|
||||
// Zooming window
|
||||
windowWillUseStandardFrameDefaultFrame: proc(window: ^Window, newFrame: Rect) -> Rect,
|
||||
windowShouldZoomToFrame: proc(window: ^Window, newFrame: Rect) -> BOOL,
|
||||
// Managing Full-Screen Presentation
|
||||
windowWillUseFullScreenContentSize: proc(window: ^Window, proposedSize: Size) -> Size,
|
||||
windowWillUseFullScreenPresentationOptions: proc(window: ^Window, proposedOptions: ApplicationPresentationOptions) -> ApplicationPresentationOptions,
|
||||
windowWillEnterFullScreen: proc(notification: ^Notification),
|
||||
windowDidEnterFullScreen: proc(notification: ^Notification),
|
||||
windowWillExitFullScreen: proc(notification: ^Notification),
|
||||
windowDidExitFullScreen: proc(notification: ^Notification),
|
||||
// Custom Full-Screen Presentation Animations
|
||||
customWindowsToEnterFullScreenForWindow: proc(window: ^Window) -> ^Array,
|
||||
customWindowsToEnterFullScreenForWindowOnScreen: proc(window: ^Window, screen: ^Screen) -> ^Array,
|
||||
windowStartCustomAnimationToEnterFullScreenWithDuration: proc(window: ^Window, duration: TimeInterval),
|
||||
windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration: proc(window: ^Window, screen: ^Screen, duration: TimeInterval),
|
||||
windowDidFailToEnterFullScreen: proc(window: ^Window),
|
||||
customWindowsToExitFullScreenForWindow: proc(window: ^Window) -> ^Array,
|
||||
windowStartCustomAnimationToExitFullScreenWithDuration: proc(window: ^Window, duration: TimeInterval),
|
||||
windowDidFailToExitFullScreen: proc(window: ^Window),
|
||||
// Moving Windows
|
||||
windowWillMove: proc(notification: ^Notification),
|
||||
windowDidMove: proc(notification: ^Notification),
|
||||
windowDidChangeScreen: proc(notification: ^Notification),
|
||||
windowDidChangeScreenProfile: proc(notification: ^Notification),
|
||||
windowDidChangeBackingProperties: proc(notification: ^Notification),
|
||||
// Closing Windows
|
||||
windowShouldClose: proc(sender: ^Window) -> BOOL,
|
||||
windowWillClose: proc(notification: ^Notification),
|
||||
// Managing Key Status
|
||||
windowDidBecomeKey: proc(notification: ^Notification),
|
||||
windowDidResignKey: proc(notification: ^Notification),
|
||||
// Managing Main Status
|
||||
windowDidBecomeMain: proc(notification: ^Notification),
|
||||
windowDidResignMain: proc(notification: ^Notification),
|
||||
// Managing Field Editors
|
||||
windowWillReturnFieldEditorToObject: proc(sender: ^Window, client: id) -> id,
|
||||
// Updating Windows
|
||||
windowDidUpdate: proc (notification: ^Notification),
|
||||
// Exposing Windows
|
||||
windowDidExpose: proc (notification: ^Notification),
|
||||
// Managing Occlusion State
|
||||
windowDidChangeOcclusionState: proc(notification: ^Notification),
|
||||
// Dragging Windows
|
||||
windowShouldDragDocumentWithEventFromWithPasteboard: proc(window: ^Window, event: ^Event, dragImageLocation: Point, pasteboard: ^Pasteboard) -> BOOL,
|
||||
// Getting the Undo Manager
|
||||
windowWillReturnUndoManager: proc(window: ^Window) -> ^UndoManager,
|
||||
// Managing Titles
|
||||
windowShouldPopUpDocumentPathMenu: proc(window: ^Window, menu: ^Menu) -> BOOL,
|
||||
// Managing Restorable State
|
||||
windowWillEncodeRestorableState: proc(window: ^Window, state: ^Coder),
|
||||
windowDidEncodeRestorableState: proc(window: ^Window, state: ^Coder),
|
||||
// Managing Presentation in Version Browsers
|
||||
windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize: proc(window: ^Window, maxPreferredFrameSize: Size, maxAllowedFrameSize: Size) -> Size,
|
||||
windowWillEnterVersionBrowser: proc(notification: ^Notification),
|
||||
windowDidEnterVersionBrowser: proc(notification: ^Notification),
|
||||
windowWillExitVersionBrowser: proc(notification: ^Notification),
|
||||
windowDidExitVersionBrowser: proc(notification: ^Notification),
|
||||
}
|
||||
|
||||
|
||||
WindowDelegate :: struct { using _: Object } // This is not the same as NSWindowDelegate
|
||||
_WindowDelegateInternal :: struct {
|
||||
using _: WindowDelegateTemplate,
|
||||
_context: runtime.Context,
|
||||
}
|
||||
|
||||
window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, class_name: string, delegate_context: Maybe(runtime.Context)) -> ^WindowDelegate {
|
||||
class := objc_allocateClassPair(intrinsics.objc_find_class("NSObject"), strings.clone_to_cstring(class_name, context.temp_allocator), 0); if class == nil {
|
||||
// Class already registered
|
||||
return nil
|
||||
}
|
||||
if template.windowWillPositionSheetUsingRect != nil {
|
||||
windowWillPositionSheetUsingRect :: proc "c" (self: id, window: ^Window, sheet: ^Window, rect: Rect) -> Rect {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowWillPositionSheetUsingRect(window, sheet, rect)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:willPositionSheet:usingRect:"), auto_cast windowWillPositionSheetUsingRect, _RECT_ENCODING+"@:@@"+_RECT_ENCODING)
|
||||
}
|
||||
if template.windowWillBeginSheet != nil {
|
||||
windowWillBeginSheet :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowWillBeginSheet(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillBeginSheet:"), auto_cast windowWillBeginSheet, "v@:@")
|
||||
}
|
||||
if template.windowDidEndSheet != nil {
|
||||
windowDidEndSheet :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidEndSheet(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidEndSheet:"), auto_cast windowDidEndSheet, "v@:@")
|
||||
}
|
||||
if template.windowWillResizeToSize != nil {
|
||||
windowWillResizeToSize :: proc "c" (self: id, sender: ^Window, frameSize: Size) -> Size {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowWillResizeToSize(sender, frameSize)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillResize:toSize:"), auto_cast windowWillResizeToSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING)
|
||||
}
|
||||
if template.windowDidResize != nil {
|
||||
windowDidResize :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidResize(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidResize:"), auto_cast windowDidResize, "v@:@")
|
||||
}
|
||||
if template.windowWillStartLiveResize != nil {
|
||||
windowWillStartLiveResize :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowWillStartLiveResize(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillStartLiveResize:"), auto_cast windowWillStartLiveResize, "v@:@")
|
||||
}
|
||||
if template.windowDidEndLiveResize != nil {
|
||||
windowDidEndLiveResize :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidEndLiveResize(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidEndLiveResize:"), auto_cast windowDidEndLiveResize, "v@:@")
|
||||
}
|
||||
if template.windowWillMiniaturize != nil {
|
||||
windowWillMiniaturize :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowWillMiniaturize(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillMiniaturize:"), auto_cast windowWillMiniaturize, "v@:@")
|
||||
}
|
||||
if template.windowDidMiniaturize != nil {
|
||||
windowDidMiniaturize :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidMiniaturize(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidMiniaturize:"), auto_cast windowDidMiniaturize, "v@:@")
|
||||
}
|
||||
if template.windowDidDeminiaturize != nil {
|
||||
windowDidDeminiaturize :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidDeminiaturize(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidDeminiaturize:"), auto_cast windowDidDeminiaturize, "v@:@")
|
||||
}
|
||||
if template.windowWillUseStandardFrameDefaultFrame != nil {
|
||||
windowWillUseStandardFrameDefaultFrame :: proc(self: id, window: ^Window, newFrame: Rect) -> Rect {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowWillUseStandardFrameDefaultFrame(window, newFrame)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillUseStandardFrame:defaultFrame:"), auto_cast windowWillUseStandardFrameDefaultFrame, _RECT_ENCODING+"@:@"+_RECT_ENCODING)
|
||||
}
|
||||
if template.windowShouldZoomToFrame != nil {
|
||||
windowShouldZoomToFrame :: proc "c" (self: id, window: ^Window, newFrame: Rect) -> BOOL {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowShouldZoomToFrame(window, newFrame)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowShouldZoom:toFrame:"), auto_cast windowShouldZoomToFrame, "B@:@"+_RECT_ENCODING)
|
||||
}
|
||||
if template.windowWillUseFullScreenContentSize != nil {
|
||||
windowWillUseFullScreenContentSize :: proc "c" (self: id, window: ^Window, proposedSize: Size) -> Size {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowWillUseFullScreenContentSize(window, proposedSize)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:willUseFullScreenContentSize:"), auto_cast windowWillUseFullScreenContentSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING)
|
||||
}
|
||||
if template.windowWillUseFullScreenPresentationOptions != nil {
|
||||
windowWillUseFullScreenPresentationOptions :: proc(self: id, window: ^Window, proposedOptions: ApplicationPresentationOptions) -> ApplicationPresentationOptions {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowWillUseFullScreenPresentationOptions(window, proposedOptions)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:willUseFullScreenPresentationOptions:"), auto_cast windowWillUseFullScreenPresentationOptions, _UINTEGER_ENCODING+"@:@"+_UINTEGER_ENCODING)
|
||||
}
|
||||
if template.windowWillEnterFullScreen != nil {
|
||||
windowWillEnterFullScreen :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowWillEnterFullScreen(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillEnterFullScreen:"), auto_cast windowWillEnterFullScreen, "v@:@")
|
||||
}
|
||||
if template.windowDidEnterFullScreen != nil {
|
||||
windowDidEnterFullScreen :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidEnterFullScreen(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidEnterFullScreen:"), auto_cast windowDidEnterFullScreen, "v@:@")
|
||||
}
|
||||
if template.windowWillExitFullScreen != nil {
|
||||
windowWillExitFullScreen :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowWillExitFullScreen(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillExitFullScreen:"), auto_cast windowWillExitFullScreen, "v@:@")
|
||||
}
|
||||
if template.windowDidExitFullScreen != nil {
|
||||
windowDidExitFullScreen :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidExitFullScreen(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidExitFullScreen:"), auto_cast windowDidExitFullScreen, "v@:@")
|
||||
}
|
||||
if template.customWindowsToEnterFullScreenForWindow != nil {
|
||||
customWindowsToEnterFullScreenForWindow :: proc "c" (self: id, window: ^Window) -> ^Array {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.customWindowsToEnterFullScreenForWindow(window)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("customWindowsToEnterFullScreenForWindow:"), auto_cast customWindowsToEnterFullScreenForWindow, "@@:@")
|
||||
}
|
||||
if template.customWindowsToEnterFullScreenForWindowOnScreen != nil {
|
||||
customWindowsToEnterFullScreenForWindowOnScreen :: proc(self: id, window: ^Window, screen: ^Screen) -> ^Array {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.customWindowsToEnterFullScreenForWindowOnScreen(window, screen)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("customWindowsToEnterFullScreenForWindow:onScreen:"), auto_cast customWindowsToEnterFullScreenForWindowOnScreen, "@@:@@")
|
||||
}
|
||||
if template.windowStartCustomAnimationToEnterFullScreenWithDuration != nil {
|
||||
windowStartCustomAnimationToEnterFullScreenWithDuration :: proc "c" (self: id, window: ^Window, duration: TimeInterval) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowStartCustomAnimationToEnterFullScreenWithDuration(window, duration)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToEnterFullScreenWithDuration:"), auto_cast windowStartCustomAnimationToEnterFullScreenWithDuration, "v@:@@")
|
||||
}
|
||||
if template.windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration != nil {
|
||||
windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration :: proc(self: id, window: ^Window, screen: ^Screen, duration: TimeInterval) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration(window, screen, duration)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToEnterFullScreenOnScreen:withDuration:"), auto_cast windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration, "v@:@@d")
|
||||
}
|
||||
if template.windowDidFailToEnterFullScreen != nil {
|
||||
windowDidFailToEnterFullScreen :: proc "c" (self: id, window: ^Window) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidFailToEnterFullScreen(window)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidFailToEnterFullScreen:"), auto_cast windowDidFailToEnterFullScreen, "v@:@")
|
||||
}
|
||||
if template.customWindowsToExitFullScreenForWindow != nil {
|
||||
customWindowsToExitFullScreenForWindow :: proc "c" (self: id, window: ^Window) -> ^Array {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.customWindowsToExitFullScreenForWindow(window)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("customWindowsToExitFullScreenForWindow:"), auto_cast customWindowsToExitFullScreenForWindow, "@@:@")
|
||||
}
|
||||
if template.windowStartCustomAnimationToExitFullScreenWithDuration != nil {
|
||||
windowStartCustomAnimationToExitFullScreenWithDuration :: proc "c" (self: id, window: ^Window, duration: TimeInterval) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowStartCustomAnimationToExitFullScreenWithDuration(window, duration)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToExitFullScreenWithDuration:"), auto_cast windowStartCustomAnimationToExitFullScreenWithDuration, "v@:@d")
|
||||
}
|
||||
if template.windowDidFailToExitFullScreen != nil {
|
||||
windowDidFailToExitFullScreen :: proc "c" (self: id, window: ^Window) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidFailToExitFullScreen(window)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidFailToExitFullScreen:"), auto_cast windowDidFailToExitFullScreen, "v@:@")
|
||||
}
|
||||
if template.windowWillMove != nil {
|
||||
windowWillMove :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowWillMove(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillMove:"), auto_cast windowWillMove, "v@:@")
|
||||
}
|
||||
if template.windowDidMove != nil {
|
||||
windowDidMove :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidMove(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidMove:"), auto_cast windowDidMove, "v@:@")
|
||||
}
|
||||
if template.windowDidChangeScreen != nil {
|
||||
windowDidChangeScreen :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidChangeScreen(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeScreen:"), auto_cast windowDidChangeScreen, "v@:@")
|
||||
}
|
||||
if template.windowDidChangeScreenProfile != nil {
|
||||
windowDidChangeScreenProfile :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidChangeScreenProfile(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeScreenProfile:"), auto_cast windowDidChangeScreenProfile, "v@:@")
|
||||
}
|
||||
if template.windowDidChangeBackingProperties != nil {
|
||||
windowDidChangeBackingProperties :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidChangeBackingProperties(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeBackingProperties:"), auto_cast windowDidChangeBackingProperties, "v@:@")
|
||||
}
|
||||
if template.windowShouldClose != nil {
|
||||
windowShouldClose :: proc "c" (self:id, sender: ^Window) -> BOOL {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowShouldClose(sender)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowShouldClose:"), auto_cast windowShouldClose, "B@:@")
|
||||
}
|
||||
if template.windowWillClose != nil {
|
||||
windowWillClose :: proc "c" (self:id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowWillClose(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillClose:"), auto_cast windowWillClose, "v@:@")
|
||||
}
|
||||
if template.windowDidBecomeKey != nil {
|
||||
windowDidBecomeKey :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidBecomeKey(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidBecomeKey:"), auto_cast windowDidBecomeKey, "v@:@")
|
||||
}
|
||||
if template.windowDidResignKey != nil {
|
||||
windowDidResignKey :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidResignKey(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidResignKey:"), auto_cast windowDidResignKey, "v@:@")
|
||||
}
|
||||
if template.windowDidBecomeMain != nil {
|
||||
windowDidBecomeMain :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidBecomeMain(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidBecomeMain:"), auto_cast windowDidBecomeMain, "v@:@")
|
||||
}
|
||||
if template.windowDidResignMain != nil {
|
||||
windowDidResignMain :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidResignMain(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidResignMain:"), auto_cast windowDidResignMain, "v@:@")
|
||||
}
|
||||
if template.windowWillReturnFieldEditorToObject != nil {
|
||||
windowWillReturnFieldEditorToObject :: proc "c" (self:id, sender: ^Window, client: id) -> id {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowWillReturnFieldEditorToObject(sender, client)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillReturnFieldEditor:toObject:"), auto_cast windowWillReturnFieldEditorToObject, "@@:@@")
|
||||
}
|
||||
if template.windowDidUpdate != nil {
|
||||
windowDidUpdate :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidUpdate(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidUpdate:"), auto_cast windowDidUpdate, "v@:@")
|
||||
}
|
||||
if template.windowDidExpose != nil {
|
||||
windowDidExpose :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidExpose(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidExpose:"), auto_cast windowDidExpose, "v@:@")
|
||||
}
|
||||
if template.windowDidChangeOcclusionState != nil {
|
||||
windowDidChangeOcclusionState :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidChangeOcclusionState(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeOcclusionState:"), auto_cast windowDidChangeOcclusionState, "v@:@")
|
||||
}
|
||||
if template.windowShouldDragDocumentWithEventFromWithPasteboard != nil {
|
||||
windowShouldDragDocumentWithEventFromWithPasteboard :: proc "c" (self: id, window: ^Window, event: ^Event, dragImageLocation: Point, pasteboard: ^Pasteboard) -> BOOL {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowShouldDragDocumentWithEventFromWithPasteboard(window, event, dragImageLocation, pasteboard)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:shouldDragDocumentWithEvent:from:withPasteboard:"), auto_cast windowShouldDragDocumentWithEventFromWithPasteboard, "B@:@@"+_POINT_ENCODING+"@")
|
||||
}
|
||||
if template.windowWillReturnUndoManager != nil {
|
||||
windowWillReturnUndoManager :: proc "c" (self: id, window: ^Window) -> ^UndoManager {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowWillReturnUndoManager(window)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillReturnUndoManager:"), auto_cast windowWillReturnUndoManager, "@@:@")
|
||||
}
|
||||
if template.windowShouldPopUpDocumentPathMenu != nil {
|
||||
windowShouldPopUpDocumentPathMenu :: proc "c" (self: id, window: ^Window, menu: ^Menu) -> BOOL {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowShouldPopUpDocumentPathMenu(window, menu)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:shouldPopUpDocumentPathMenu:"), auto_cast windowShouldPopUpDocumentPathMenu, "B@:@@")
|
||||
}
|
||||
if template.windowWillEncodeRestorableState != nil {
|
||||
windowWillEncodeRestorableState :: proc "c" (self: id, window: ^Window, state: ^Coder) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowWillEncodeRestorableState(window, state)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:willEncodeRestorableState:"), auto_cast windowWillEncodeRestorableState, "v@:@@")
|
||||
}
|
||||
if template.windowDidEncodeRestorableState != nil {
|
||||
windowDidEncodeRestorableState :: proc "c" (self: id, window: ^Window, state: ^Coder) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidEncodeRestorableState(window, state)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:didDecodeRestorableState:"), auto_cast windowDidEncodeRestorableState, "v@:@@")
|
||||
}
|
||||
if template.windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize != nil {
|
||||
windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize :: proc "c" (self: id, window: ^Window, maxPreferredFrameSize: Size, maxAllowedFrameSize: Size) -> Size {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
return del.windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize(window, maxPreferredFrameSize, maxPreferredFrameSize)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("window:willResizeForVersionBrowserWithMaxPreferredSize:maxAllowedSize:"), auto_cast windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING+_SIZE_ENCODING)
|
||||
}
|
||||
if template.windowWillEnterVersionBrowser != nil {
|
||||
windowWillEnterVersionBrowser :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowWillEnterVersionBrowser(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillEnterVersionBrowser:"), auto_cast windowWillEnterVersionBrowser, "v@:@")
|
||||
}
|
||||
if template.windowDidEnterVersionBrowser != nil {
|
||||
windowDidEnterVersionBrowser :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidEnterVersionBrowser(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidEnterVersionBrowser:"), auto_cast windowDidEnterVersionBrowser, "v@:@")
|
||||
}
|
||||
if template.windowWillExitVersionBrowser != nil {
|
||||
windowWillExitVersionBrowser :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowWillExitVersionBrowser(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowWillExitVersionBrowser:"), auto_cast windowWillExitVersionBrowser, "v@:@")
|
||||
}
|
||||
if template.windowDidExitVersionBrowser != nil {
|
||||
windowDidExitVersionBrowser :: proc "c" (self: id, notification: ^Notification) {
|
||||
del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
|
||||
context = del._context
|
||||
del.windowDidExitVersionBrowser(notification)
|
||||
}
|
||||
class_addMethod(class, intrinsics.objc_find_selector("windowDidExitVersionBrowser:"), auto_cast windowDidExitVersionBrowser, "v@:@")
|
||||
}
|
||||
|
||||
objc_registerClassPair(class)
|
||||
del := class_createInstance(class, size_of(_WindowDelegateInternal))
|
||||
del_internal := cast(^_WindowDelegateInternal)object_getIndexedIvars(del)
|
||||
del_internal^ = {
|
||||
template,
|
||||
delegate_context.(runtime.Context) or_else runtime.default_context(),
|
||||
}
|
||||
|
||||
return cast(^WindowDelegate)del
|
||||
}
|
||||
|
||||
@(objc_class="CALayer")
|
||||
Layer :: struct { using _: Object }
|
||||
|
||||
@(objc_type=Layer, objc_name="contentsScale")
|
||||
Layer_contentsScale :: proc "c" (self: ^Layer) -> Float {
|
||||
return msgSend(Float, self, "contentsScale")
|
||||
}
|
||||
@(objc_type=Layer, objc_name="setContentsScale")
|
||||
Layer_setContentsScale :: proc "c" (self: ^Layer, scale: Float) {
|
||||
msgSend(nil, self, "setContentsScale:", scale)
|
||||
}
|
||||
@(objc_type=Layer, objc_name="frame")
|
||||
Layer_frame :: proc "c" (self: ^Layer) -> Rect {
|
||||
return msgSend(Rect, self, "frame")
|
||||
}
|
||||
@(objc_type=Layer, objc_name="addSublayer")
|
||||
Layer_addSublayer :: proc "c" (self: ^Layer, layer: ^Layer) {
|
||||
msgSend(nil, self, "addSublayer:", layer)
|
||||
}
|
||||
|
||||
@(objc_class="NSResponder")
|
||||
Responder :: struct {using _: Object}
|
||||
|
||||
@(objc_class="NSView")
|
||||
View :: struct {using _: Responder}
|
||||
|
||||
|
||||
@(objc_type=View, objc_name="initWithFrame")
|
||||
View_initWithFrame :: proc "c" (self: ^View, frame: Rect) -> ^View {
|
||||
return msgSend(^View, self, "initWithFrame:", frame)
|
||||
}
|
||||
@(objc_type=View, objc_name="bounds")
|
||||
View_bounds :: proc "c" (self: ^View) -> Rect {
|
||||
return msgSend(Rect, self, "bounds")
|
||||
}
|
||||
@(objc_type=View, objc_name="layer")
|
||||
View_layer :: proc "c" (self: ^View) -> ^Layer {
|
||||
return msgSend(^Layer, self, "layer")
|
||||
}
|
||||
@(objc_type=View, objc_name="setLayer")
|
||||
View_setLayer :: proc "c" (self: ^View, layer: ^Layer) {
|
||||
msgSend(nil, self, "setLayer:", layer)
|
||||
}
|
||||
@(objc_type=View, objc_name="wantsLayer")
|
||||
View_wantsLayer :: proc "c" (self: ^View) -> BOOL {
|
||||
return msgSend(BOOL, self, "wantsLayer")
|
||||
}
|
||||
@(objc_type=View, objc_name="setWantsLayer")
|
||||
View_setWantsLayer :: proc "c" (self: ^View, wantsLayer: BOOL) {
|
||||
msgSend(nil, self, "setWantsLayer:", wantsLayer)
|
||||
}
|
||||
@(objc_type=View, objc_name="convertPointFromView")
|
||||
View_convertPointFromView :: proc "c" (self: ^View, point: Point, view: ^View) -> Point {
|
||||
return msgSend(Point, self, "convertPoint:fromView:", point, view)
|
||||
}
|
||||
|
||||
@(objc_class="NSWindow")
|
||||
Window :: struct {using _: Responder}
|
||||
|
||||
@(objc_type=Window, objc_name="alloc", objc_is_class_method=true)
|
||||
Window_alloc :: proc "c" () -> ^Window {
|
||||
return msgSend(^Window, Window, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Window, objc_name="initWithContentRect")
|
||||
Window_initWithContentRect :: proc (self: ^Window, contentRect: Rect, styleMask: WindowStyleMask, backing: BackingStoreType, doDefer: BOOL) -> ^Window {
|
||||
self := self
|
||||
// HACK: due to a compiler bug, the generated calling code does not
|
||||
// currently work for this message. Has to do with passing a struct along
|
||||
// with other parameters, so we don't send the rect here.
|
||||
// Omiting the rect argument here actually works, because of how the C
|
||||
// calling conventions are defined.
|
||||
self = msgSend(^Window, self, "initWithContentRect:styleMask:backing:defer:", styleMask, backing, doDefer)
|
||||
|
||||
// apply the contentRect now, since we did not pass it to the init call
|
||||
msgSend(nil, self, "setContentSize:", contentRect.size)
|
||||
msgSend(nil, self, "setFrameOrigin:", contentRect.origin)
|
||||
return self
|
||||
}
|
||||
@(objc_type=Window, objc_name="contentView")
|
||||
Window_contentView :: proc "c" (self: ^Window) -> ^View {
|
||||
return msgSend(^View, self, "contentView")
|
||||
}
|
||||
@(objc_type=Window, objc_name="setContentView")
|
||||
Window_setContentView :: proc "c" (self: ^Window, content_view: ^View) {
|
||||
msgSend(nil, self, "setContentView:", content_view)
|
||||
}
|
||||
@(objc_type=Window, objc_name="contentLayoutRect")
|
||||
Window_contentLayoutRect :: proc "c" (self: ^Window) -> Rect {
|
||||
return msgSend(Rect, self, "contentLayoutRect")
|
||||
}
|
||||
@(objc_type=Window, objc_name="frame")
|
||||
Window_frame :: proc "c" (self: ^Window) -> Rect {
|
||||
return msgSend(Rect, self, "frame")
|
||||
}
|
||||
@(objc_type=Window, objc_name="setFrame")
|
||||
Window_setFrame :: proc "c" (self: ^Window, frame: Rect) {
|
||||
msgSend(nil, self, "setFrame:", frame)
|
||||
}
|
||||
@(objc_type=Window, objc_name="opaque")
|
||||
Window_opaque :: proc "c" (self: ^Window) -> BOOL {
|
||||
return msgSend(BOOL, self, "opaque")
|
||||
}
|
||||
@(objc_type=Window, objc_name="setOpaque")
|
||||
Window_setOpaque :: proc "c" (self: ^Window, ok: BOOL) {
|
||||
msgSend(nil, self, "setOpaque:", ok)
|
||||
}
|
||||
@(objc_type=Window, objc_name="backgroundColor")
|
||||
Window_backgroundColor :: proc "c" (self: ^Window) -> ^Color {
|
||||
return msgSend(^Color, self, "backgroundColor")
|
||||
}
|
||||
@(objc_type=Window, objc_name="setBackgroundColor")
|
||||
Window_setBackgroundColor :: proc "c" (self: ^Window, color: ^Color) {
|
||||
msgSend(nil, self, "setBackgroundColor:", color)
|
||||
}
|
||||
@(objc_type=Window, objc_name="makeKeyAndOrderFront")
|
||||
Window_makeKeyAndOrderFront :: proc "c" (self: ^Window, key: ^Object) {
|
||||
msgSend(nil, self, "makeKeyAndOrderFront:", key)
|
||||
}
|
||||
@(objc_type=Window, objc_name="setTitle")
|
||||
Window_setTitle :: proc "c" (self: ^Window, title: ^String) {
|
||||
msgSend(nil, self, "setTitle:", title)
|
||||
}
|
||||
@(objc_type=Window, objc_name="setTitlebarAppearsTransparent")
|
||||
Window_setTitlebarAppearsTransparent :: proc "c" (self: ^Window, ok: BOOL) {
|
||||
msgSend(nil, self, "setTitlebarAppearsTransparent:", ok)
|
||||
}
|
||||
@(objc_type=Window, objc_name="setMovable")
|
||||
Window_setMovable :: proc "c" (self: ^Window, ok: BOOL) {
|
||||
msgSend(nil, self, "setMovable:", ok)
|
||||
}
|
||||
@(objc_type=Window, objc_name="setMovableByWindowBackground")
|
||||
Window_setMovableByWindowBackground :: proc "c" (self: ^Window, ok: BOOL) {
|
||||
msgSend(nil, self, "setMovableByWindowBackground:", ok)
|
||||
}
|
||||
@(objc_type=Window, objc_name="setStyleMask")
|
||||
Window_setStyleMask :: proc "c" (self: ^Window, style_mask: WindowStyleMask) {
|
||||
msgSend(nil, self, "setStyleMask:", style_mask)
|
||||
}
|
||||
@(objc_type=Window, objc_name="close")
|
||||
Window_close :: proc "c" (self: ^Window) {
|
||||
msgSend(nil, self, "close")
|
||||
}
|
||||
@(objc_type=Window, objc_name="setDelegate")
|
||||
Window_setDelegate :: proc "c" (self: ^Window, delegate: ^WindowDelegate) {
|
||||
msgSend(nil, self, "setDelegate:", delegate)
|
||||
}
|
||||
@(objc_type=Window, objc_name="backingScaleFactor")
|
||||
Window_backingScaleFactor :: proc "c" (self: ^Window) -> Float {
|
||||
return msgSend(Float, self, "backingScaleFactor")
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package objc_Foundation
|
||||
|
||||
foreign import "system:Foundation.framework"
|
||||
// NOTE: Most of our bindings are reliant on Cocoa (everything under appkit) so just unconditionally import it
|
||||
@(require) foreign import "system:Cocoa.framework"
|
||||
|
||||
import "base:intrinsics"
|
||||
import "core:c"
|
||||
|
||||
IMP :: proc "c" (object: id, sel: SEL, #c_vararg args: ..any) -> id
|
||||
|
||||
foreign Foundation {
|
||||
objc_lookUpClass :: proc "c" (name: cstring) -> Class ---
|
||||
sel_registerName :: proc "c" (name: cstring) -> SEL ---
|
||||
objc_allocateClassPair :: proc "c" (superclass : Class, name : cstring, extraBytes : c.size_t) -> Class ---
|
||||
objc_registerClassPair :: proc "c" (cls : Class) ---
|
||||
|
||||
class_addMethod :: proc "c" (cls: Class, name: SEL, imp: IMP, types: cstring) -> BOOL ---
|
||||
class_getInstanceMethod :: proc "c" (cls: Class, name: SEL) -> Method ---
|
||||
class_createInstance :: proc "c" (cls: Class, extraBytes: c.size_t) -> id ---
|
||||
|
||||
method_setImplementation :: proc "c" (method: Method, imp: IMP) ---
|
||||
object_getIndexedIvars :: proc(obj: id) -> rawptr ---
|
||||
}
|
||||
|
||||
|
||||
@(objc_class="NSZone")
|
||||
Zone :: struct {using _: Object}
|
||||
|
||||
@(link_prefix="NS")
|
||||
foreign Foundation {
|
||||
AllocateObject :: proc "c" (aClass: Class, extraBytes: UInteger, zone: ^Zone) -> id ---
|
||||
DeallocateObject :: proc "c" (object: id) ---
|
||||
}
|
||||
|
||||
Method :: ^objc_method
|
||||
objc_method :: struct {
|
||||
method_name: SEL,
|
||||
method_types: cstring,
|
||||
method_imp: IMP,
|
||||
}
|
||||
objc_method_list :: struct {}
|
||||
|
||||
objc_ivar :: struct {}
|
||||
objc_ivar_list :: struct {}
|
||||
|
||||
objc_cache :: struct {
|
||||
mask: u32,
|
||||
occupied: u32,
|
||||
buckets: [1]Method,
|
||||
}
|
||||
|
||||
objc_protocol_list :: struct {
|
||||
next: ^objc_protocol_list,
|
||||
count: c.int,
|
||||
list: [1]^Protocol,
|
||||
}
|
||||
|
||||
@(objc_class="Protocol")
|
||||
Protocol :: struct{using _: intrinsics.objc_object}
|
||||
|
||||
objc_object_internals :: struct {
|
||||
isa: ^objc_class_internals,
|
||||
}
|
||||
|
||||
|
||||
objc_class_internals :: struct {
|
||||
isa: Class,
|
||||
super_class: Class,
|
||||
name: cstring,
|
||||
version: c.long,
|
||||
info: c.long,
|
||||
instance_size: c.long,
|
||||
ivars: ^objc_ivar_list,
|
||||
|
||||
methodLists: ^^objc_method_list,
|
||||
|
||||
cache: rawptr,
|
||||
protocols: rawptr,
|
||||
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
package Security
|
||||
|
||||
OSStatus :: distinct i32
|
||||
|
||||
errSec :: enum OSStatus {
|
||||
Success = 0, // No error.
|
||||
Unimplemented = -4, // Function or operation not implemented.
|
||||
DiskFull = -34, // The disk is full.
|
||||
IO = -36, // I/O error.
|
||||
OpWr = -49, // File already open with with write permission.
|
||||
Param = -50, // One or more parameters passed to a function were not valid.
|
||||
WrPerm = -61, // Write permissions error.
|
||||
Allocate = -108, // Failed to allocate memory.
|
||||
UserCanceled = -128, // User canceled the operation.
|
||||
BadReq = -909, // Bad parameter or invalid state for operation.
|
||||
InternalComponent = -2070,
|
||||
CoreFoundationUnknown = -4960,
|
||||
MissingEntitlement, // A required entitlement isn't present.
|
||||
RestrictedAPI, // Client is restricted and is not permitted to perform this operation.
|
||||
NotAvailable = -25291, // No keychain is available. You may need to restart your computer.
|
||||
ReadOnly = -25292, // This keychain cannot be modified.
|
||||
AuthFailed = -25293, // The user name or passphrase you entered is not correct.
|
||||
NoSuchKeychain = -25294, // The specified keychain could not be found.
|
||||
InvalidKeychain = -25295, // The specified keychain is not a valid keychain file.
|
||||
DuplicateKeychain = -25296, // A keychain with the same name already exists.
|
||||
DuplicateCallback = -25297, // The specified callback function is already installed.
|
||||
InvalidCallback = -25298, // The specified callback function is not valid.
|
||||
DuplicateItem = -25299, // The specified item already exists in the keychain.
|
||||
ItemNotFound = -25300, // The specified item could not be found in the keychain.
|
||||
BufferTooSmall = -25301, // There is not enough memory available to use the specified item.
|
||||
DataTooLarge = -25302, // This item contains information which is too large or in a format that cannot be displayed.
|
||||
NoSuchAttr = -25303, // The specified attribute does not exist.
|
||||
InvalidItemRef = -25304, // The specified item is no longer valid. It may have been deleted from the keychain.
|
||||
InvalidSearchRef = -25305, // Unable to search the current keychain.
|
||||
NoSuchClass = -25306, // The specified item does not appear to be a valid keychain item.
|
||||
NoDefaultKeychain = -25307, // A default keychain could not be found.
|
||||
InteractionNotAllowed = -25308, // User interaction is not allowed.
|
||||
ReadOnlyAttr = -25309, // The specified attribute could not be modified.
|
||||
WrongSecVersion = -25310, // This keychain was created by a different version of the system software and cannot be opened.
|
||||
KeySizeNotAllowed = -25311, // This item specifies a key size which is too large or too small.
|
||||
NoStorageModule = -25312, // A required component (data storage module) could not be loaded. You may need to restart your computer.
|
||||
NoCertificateModule = -25313, // A required component (certificate module) could not be loaded. You may need to restart your computer.
|
||||
NoPolicyModule = -25314, // A required component (policy module) could not be loaded. You may need to restart your computer.
|
||||
InteractionRequired = -25315, // User interaction is required, but is currently not allowed.
|
||||
DataNotAvailable = -25316, // The contents of this item cannot be retrieved.
|
||||
DataNotModifiable = -25317, // The contents of this item cannot be modified.
|
||||
CreateChainFailed = -25318, // One or more certificates required to validate this certificate cannot be found.
|
||||
InvalidPrefsDomain = -25319, // The specified preferences domain is not valid.
|
||||
InDarkWake = -25320, // In dark wake, no UI possible
|
||||
ACLNotSimple = -25240, // The specified access control list is not in standard (simple) form.
|
||||
PolicyNotFound = -25241, // The specified policy cannot be found.
|
||||
InvalidTrustSetting = -25242, // The specified trust setting is invalid.
|
||||
NoAccessForItem = -25243, // The specified item has no access control.
|
||||
InvalidOwnerEdit = -25244, // Invalid attempt to change the owner of this item.
|
||||
TrustNotAvailable = -25245, // No trust results are available.
|
||||
UnsupportedFormat = -25256, // Import/Export format unsupported.
|
||||
UnknownFormat = -25257, // Unknown format in import.
|
||||
KeyIsSensitive = -25258, // Key material must be wrapped for export.
|
||||
MultiplePrivKeys = -25259, // An attempt was made to import multiple private keys.
|
||||
PassphraseRequired = -25260, // Passphrase is required for import/export.
|
||||
InvalidPasswordRef = -25261, // The password reference was invalid.
|
||||
InvalidTrustSettings = -25262, // The Trust Settings Record was corrupted.
|
||||
NoTrustSettings = -25263, // No Trust Settings were found.
|
||||
Pkcs12VerifyFailure = -25264, // MAC verification failed during PKCS12 import (wrong password?)
|
||||
NotSigner = -26267, // A certificate was not signed by its proposed parent.
|
||||
Decode = -26275, // Unable to decode the provided data.
|
||||
ServiceNotAvailable = -67585, // The required service is not available.
|
||||
InsufficientClientID = -67586, // The client ID is not correct.
|
||||
DeviceReset = -67587, // A device reset has occurred.
|
||||
DeviceFailed = -67588, // A device failure has occurred.
|
||||
AppleAddAppACLSubject = -67589, // Adding an application ACL subject failed.
|
||||
ApplePublicKeyIncomplete = -67590, // The public key is incomplete.
|
||||
AppleSignatureMismatch = -67591, // A signature mismatch has occurred.
|
||||
AppleInvalidKeyStartDate = -67592, // The specified key has an invalid start date.
|
||||
AppleInvalidKeyEndDate = -67593, // The specified key has an invalid end date.
|
||||
ConversionError = -67594, // A conversion error has occurred.
|
||||
AppleSSLv2Rollback = -67595, // A SSLv2 rollback error has occurred.
|
||||
QuotaExceeded = -67596, // The quota was exceeded.
|
||||
FileTooBig = -67597, // The file is too big.
|
||||
InvalidDatabaseBlob = -67598, // The specified database has an invalid blob.
|
||||
InvalidKeyBlob = -67599, // The specified database has an invalid key blob.
|
||||
IncompatibleDatabaseBlob = -67600, // The specified database has an incompatible blob.
|
||||
IncompatibleKeyBlob = -67601, // The specified database has an incompatible key blob.
|
||||
HostNameMismatch = -67602, // A host name mismatch has occurred.
|
||||
UnknownCriticalExtensionFlag = -67603, // There is an unknown critical extension flag.
|
||||
NoBasicConstraints = -67604, // No basic constraints were found.
|
||||
NoBasicConstraintsCA = -67605, // No basic CA constraints were found.
|
||||
InvalidAuthorityKeyID = -67606, // The authority key ID is not valid.
|
||||
InvalidSubjectKeyID = -67607, // The subject key ID is not valid.
|
||||
InvalidKeyUsageForPolicy = -67608, // The key usage is not valid for the specified policy.
|
||||
InvalidExtendedKeyUsage = -67609, // The extended key usage is not valid.
|
||||
InvalidIDLinkage = -67610, // The ID linkage is not valid.
|
||||
PathLengthConstraintExceeded = -67611, // The path length constraint was exceeded.
|
||||
InvalidRoot = -67612, // The root or anchor certificate is not valid.
|
||||
CRLExpired = -67613, // The CRL has expired.
|
||||
CRLNotValidYet = -67614, // The CRL is not yet valid.
|
||||
CRLNotFound = -67615, // The CRL was not found.
|
||||
CRLServerDown = -67616, // The CRL server is down.
|
||||
CRLBadURI = -67617, // The CRL has a bad Uniform Resource Identifier.
|
||||
UnknownCertExtension = -67618, // An unknown certificate extension was encountered.
|
||||
UnknownCRLExtension = -67619, // An unknown CRL extension was encountered.
|
||||
CRLNotTrusted = -67620, // The CRL is not trusted.
|
||||
CRLPolicyFailed = -67621, // The CRL policy failed.
|
||||
IDPFailure = -67622, // The issuing distribution point was not valid.
|
||||
SMIMEEmailAddressesNotFound = -67623, // An email address mismatch was encountered.
|
||||
SMIMEBadExtendedKeyUsage = -67624, // The appropriate extended key usage for SMIME was not found.
|
||||
SMIMEBadKeyUsage = -67625, // The key usage is not compatible with SMIME.
|
||||
SMIMEKeyUsageNotCritical = -67626, // The key usage extension is not marked as critical.
|
||||
SMIMENoEmailAddress = -67627, // No email address was found in the certificate.
|
||||
SMIMESubjAltNameNotCritical = -67628, // The subject alternative name extension is not marked as critical.
|
||||
SSLBadExtendedKeyUsage = -67629, // The appropriate extended key usage for SSL was not found.
|
||||
OCSPBadResponse = -67630, // The OCSP response was incorrect or could not be parsed.
|
||||
OCSPBadRequest = -67631, // The OCSP request was incorrect or could not be parsed.
|
||||
OCSPUnavailable = -67632, // OCSP service is unavailable.
|
||||
OCSPStatusUnrecognized = -67633, // The OCSP server did not recognize this certificate.
|
||||
EndOfData = -67634, // An end-of-data was detected.
|
||||
IncompleteCertRevocationCheck = -67635, // An incomplete certificate revocation check occurred.
|
||||
NetworkFailure = -67636, // A network failure occurred.
|
||||
OCSPNotTrustedToAnchor = -67637, // The OCSP response was not trusted to a root or anchor certificate.
|
||||
RecordModified = -67638, // The record was modified.
|
||||
OCSPSignatureError = -67639, // The OCSP response had an invalid signature.
|
||||
OCSPNoSigner = -67640, // The OCSP response had no signer.
|
||||
OCSPResponderMalformedReq = -67641, // The OCSP responder was given a malformed request.
|
||||
OCSPResponderInternalError = -67642, // The OCSP responder encountered an internal error.
|
||||
OCSPResponderTryLater = -67643, // The OCSP responder is busy, try again later.
|
||||
OCSPResponderSignatureRequired = -67644, // The OCSP responder requires a signature.
|
||||
OCSPResponderUnauthorized = -67645, // The OCSP responder rejected this request as unauthorized.
|
||||
OCSPResponseNonceMismatch = -67646, // The OCSP response nonce did not match the request.
|
||||
CodeSigningBadCertChainLength = -67647, // Code signing encountered an incorrect certificate chain length.
|
||||
CodeSigningNoBasicConstraints = -67648, // Code signing found no basic constraints.
|
||||
CodeSigningBadPathLengthConstraint = -67649, // Code signing encountered an incorrect path length constraint.
|
||||
CodeSigningNoExtendedKeyUsage = -67650, // Code signing found no extended key usage.
|
||||
CodeSigningDevelopment = -67651, // Code signing indicated use of a development-only certificate.
|
||||
ResourceSignBadCertChainLength = -67652, // Resource signing has encountered an incorrect certificate chain length.
|
||||
ResourceSignBadExtKeyUsage = -67653, // Resource signing has encountered an error in the extended key usage.
|
||||
TrustSettingDeny = -67654, // The trust setting for this policy was set to Deny.
|
||||
InvalidSubjectName = -67655, // An invalid certificate subject name was encountered.
|
||||
UnknownQualifiedCertStatement = -67656, // An unknown qualified certificate statement was encountered.
|
||||
MobileMeRequestQueued = -67657,
|
||||
MobileMeRequestRedirected = -67658,
|
||||
MobileMeServerError = -67659,
|
||||
MobileMeServerNotAvailable = -67660,
|
||||
MobileMeServerAlreadyExists = -67661,
|
||||
MobileMeServerServiceErr = -67662,
|
||||
MobileMeRequestAlreadyPending = -67663,
|
||||
MobileMeNoRequestPending = -67664,
|
||||
MobileMeCSRVerifyFailure = -67665,
|
||||
MobileMeFailedConsistencyCheck = -67666,
|
||||
NotInitialized = -67667, // A function was called without initializing CSSM.
|
||||
InvalidHandleUsage = -67668, // The CSSM handle does not match with the service type.
|
||||
PVCReferentNotFound = -67669, // A reference to the calling module was not found in the list of authorized callers.
|
||||
FunctionIntegrityFail = -67670, // A function address was not within the verified module.
|
||||
InternalError = -67671, // An internal error has occurred.
|
||||
MemoryError = -67672, // A memory error has occurred.
|
||||
InvalidData = -67673, // Invalid data was encountered.
|
||||
MDSError = -67674, // A Module Directory Service error has occurred.
|
||||
InvalidPointer = -67675, // An invalid pointer was encountered.
|
||||
SelfCheckFailed = -67676, // Self-check has failed.
|
||||
FunctionFailed = -67677, // A function has failed.
|
||||
ModuleManifestVerifyFailed = -67678, // A module manifest verification failure has occurred.
|
||||
InvalidGUID = -67679, // An invalid GUID was encountered.
|
||||
InvalidHandle = -67680, // An invalid handle was encountered.
|
||||
InvalidDBList = -67681, // An invalid DB list was encountered.
|
||||
InvalidPassthroughID = -67682, // An invalid passthrough ID was encountered.
|
||||
InvalidNetworkAddress = -67683, // An invalid network address was encountered.
|
||||
CRLAlreadySigned = -67684, // The certificate revocation list is already signed.
|
||||
InvalidNumberOfFields = -67685, // An invalid number of fields were encountered.
|
||||
VerificationFailure = -67686, // A verification failure occurred.
|
||||
UnknownTag = -67687, // An unknown tag was encountered.
|
||||
InvalidSignature = -67688, // An invalid signature was encountered.
|
||||
InvalidName = -67689, // An invalid name was encountered.
|
||||
InvalidCertificateRef = -67690, // An invalid certificate reference was encountered.
|
||||
InvalidCertificateGroup = -67691, // An invalid certificate group was encountered.
|
||||
TagNotFound = -67692, // The specified tag was not found.
|
||||
InvalidQuery = -67693, // The specified query was not valid.
|
||||
InvalidValue = -67694, // An invalid value was detected.
|
||||
CallbackFailed = -67695, // A callback has failed.
|
||||
ACLDeleteFailed = -67696, // An ACL delete operation has failed.
|
||||
ACLReplaceFailed = -67697, // An ACL replace operation has failed.
|
||||
ACLAddFailed = -67698, // An ACL add operation has failed.
|
||||
ACLChangeFailed = -67699, // An ACL change operation has failed.
|
||||
InvalidAccessCredentials = -67700, // Invalid access credentials were encountered.
|
||||
InvalidRecord = -67701, // An invalid record was encountered.
|
||||
InvalidACL = -67702, // An invalid ACL was encountered.
|
||||
InvalidSampleValue = -67703, // An invalid sample value was encountered.
|
||||
IncompatibleVersion = -67704, // An incompatible version was encountered.
|
||||
PrivilegeNotGranted = -67705, // The privilege was not granted.
|
||||
InvalidScope = -67706, // An invalid scope was encountered.
|
||||
PVCAlreadyConfigured = -67707, // The PVC is already configured.
|
||||
InvalidPVC = -67708, // An invalid PVC was encountered.
|
||||
EMMLoadFailed = -67709, // The EMM load has failed.
|
||||
EMMUnloadFailed = -67710, // The EMM unload has failed.
|
||||
AddinLoadFailed = -67711, // The add-in load operation has failed.
|
||||
InvalidKeyRef = -67712, // An invalid key was encountered.
|
||||
InvalidKeyHierarchy = -67713, // An invalid key hierarchy was encountered.
|
||||
AddinUnloadFailed = -67714, // The add-in unload operation has failed.
|
||||
LibraryReferenceNotFound = -67715, // A library reference was not found.
|
||||
InvalidAddinFunctionTable = -67716, // An invalid add-in function table was encountered.
|
||||
InvalidServiceMask = -67717, // An invalid service mask was encountered.
|
||||
ModuleNotLoaded = -67718, // A module was not loaded.
|
||||
InvalidSubServiceID = -67719, // An invalid subservice ID was encountered.
|
||||
AttributeNotInContext = -67720, // An attribute was not in the context.
|
||||
ModuleManagerInitializeFailed = -67721, // A module failed to initialize.
|
||||
ModuleManagerNotFound = -67722, // A module was not found.
|
||||
EventNotificationCallbackNotFound = -67723, // An event notification callback was not found.
|
||||
InputLengthError = -67724, // An input length error was encountered.
|
||||
OutputLengthError = -67725, // An output length error was encountered.
|
||||
PrivilegeNotSupported = -67726, // The privilege is not supported.
|
||||
DeviceError = -67727, // A device error was encountered.
|
||||
AttachHandleBusy = -67728, // The CSP handle was busy.
|
||||
NotLoggedIn = -67729, // You are not logged in.
|
||||
AlgorithmMismatch = -67730, // An algorithm mismatch was encountered.
|
||||
KeyUsageIncorrect = -67731, // The key usage is incorrect.
|
||||
KeyBlobTypeIncorrect = -67732, // The key blob type is incorrect.
|
||||
KeyHeaderInconsistent = -67733, // The key header is inconsistent.
|
||||
UnsupportedKeyFormat = -67734, // The key header format is not supported.
|
||||
UnsupportedKeySize = -67735, // The key size is not supported.
|
||||
InvalidKeyUsageMask = -67736, // The key usage mask is not valid.
|
||||
UnsupportedKeyUsageMask = -67737, // The key usage mask is not supported.
|
||||
InvalidKeyAttributeMask = -67738, // The key attribute mask is not valid.
|
||||
UnsupportedKeyAttributeMask = -67739, // The key attribute mask is not supported.
|
||||
InvalidKeyLabel = -67740, // The key label is not valid.
|
||||
UnsupportedKeyLabel = -67741, // The key label is not supported.
|
||||
InvalidKeyFormat = -67742, // The key format is not valid.
|
||||
UnsupportedVectorOfBuffers = -67743, // The vector of buffers is not supported.
|
||||
InvalidInputVector = -67744, // The input vector is not valid.
|
||||
InvalidOutputVector = -67745, // The output vector is not valid.
|
||||
InvalidContext = -67746, // An invalid context was encountered.
|
||||
InvalidAlgorithm = -67747, // An invalid algorithm was encountered.
|
||||
InvalidAttributeKey = -67748, // A key attribute was not valid.
|
||||
MissingAttributeKey = -67749, // A key attribute was missing.
|
||||
InvalidAttributeInitVector = -67750, // An init vector attribute was not valid.
|
||||
MissingAttributeInitVector = -67751, // An init vector attribute was missing.
|
||||
InvalidAttributeSalt = -67752, // A salt attribute was not valid.
|
||||
MissingAttributeSalt = -67753, // A salt attribute was missing.
|
||||
InvalidAttributePadding = -67754, // A padding attribute was not valid.
|
||||
MissingAttributePadding = -67755, // A padding attribute was missing.
|
||||
InvalidAttributeRandom = -67756, // A random number attribute was not valid.
|
||||
MissingAttributeRandom = -67757, // A random number attribute was missing.
|
||||
InvalidAttributeSeed = -67758, // A seed attribute was not valid.
|
||||
MissingAttributeSeed = -67759, // A seed attribute was missing.
|
||||
InvalidAttributePassphrase = -67760, // A passphrase attribute was not valid.
|
||||
MissingAttributePassphrase = -67761, // A passphrase attribute was missing.
|
||||
InvalidAttributeKeyLength = -67762, // A key length attribute was not valid.
|
||||
MissingAttributeKeyLength = -67763, // A key length attribute was missing.
|
||||
InvalidAttributeBlockSize = -67764, // A block size attribute was not valid.
|
||||
MissingAttributeBlockSize = -67765, // A block size attribute was missing.
|
||||
InvalidAttributeOutputSize = -67766, // An output size attribute was not valid.
|
||||
MissingAttributeOutputSize = -67767, // An output size attribute was missing.
|
||||
InvalidAttributeRounds = -67768, // The number of rounds attribute was not valid.
|
||||
MissingAttributeRounds = -67769, // The number of rounds attribute was missing.
|
||||
InvalidAlgorithmParms = -67770, // An algorithm parameters attribute was not valid.
|
||||
MissingAlgorithmParms = -67771, // An algorithm parameters attribute was missing.
|
||||
InvalidAttributeLabel = -67772, // A label attribute was not valid.
|
||||
MissingAttributeLabel = -67773, // A label attribute was missing.
|
||||
InvalidAttributeKeyType = -67774, // A key type attribute was not valid.
|
||||
MissingAttributeKeyType = -67775, // A key type attribute was missing.
|
||||
InvalidAttributeMode = -67776, // A mode attribute was not valid.
|
||||
MissingAttributeMode = -67777, // A mode attribute was missing.
|
||||
InvalidAttributeEffectiveBits = -67778, // An effective bits attribute was not valid.
|
||||
MissingAttributeEffectiveBits = -67779, // An effective bits attribute was missing.
|
||||
InvalidAttributeStartDate = -67780, // A start date attribute was not valid.
|
||||
MissingAttributeStartDate = -67781, // A start date attribute was missing.
|
||||
InvalidAttributeEndDate = -67782, // An end date attribute was not valid.
|
||||
MissingAttributeEndDate = -67783, // An end date attribute was missing.
|
||||
InvalidAttributeVersion = -67784, // A version attribute was not valid.
|
||||
MissingAttributeVersion = -67785, // A version attribute was missing.
|
||||
InvalidAttributePrime = -67786, // A prime attribute was not valid.
|
||||
MissingAttributePrime = -67787, // A prime attribute was missing.
|
||||
InvalidAttributeBase = -67788, // A base attribute was not valid.
|
||||
MissingAttributeBase = -67789, // A base attribute was missing.
|
||||
InvalidAttributeSubprime = -67790, // A subprime attribute was not valid.
|
||||
MissingAttributeSubprime = -67791, // A subprime attribute was missing.
|
||||
InvalidAttributeIterationCount = -67792, // An iteration count attribute was not valid.
|
||||
MissingAttributeIterationCount = -67793, // An iteration count attribute was missing.
|
||||
InvalidAttributeDLDBHandle = -67794, // A database handle attribute was not valid.
|
||||
MissingAttributeDLDBHandle = -67795, // A database handle attribute was missing.
|
||||
InvalidAttributeAccessCredentials = -67796, // An access credentials attribute was not valid.
|
||||
MissingAttributeAccessCredentials = -67797, // An access credentials attribute was missing.
|
||||
InvalidAttributePublicKeyFormat = -67798, // A public key format attribute was not valid.
|
||||
MissingAttributePublicKeyFormat = -67799, // A public key format attribute was missing.
|
||||
InvalidAttributePrivateKeyFormat = -67800, // A private key format attribute was not valid.
|
||||
MissingAttributePrivateKeyFormat = -67801, // A private key format attribute was missing.
|
||||
InvalidAttributeSymmetricKeyFormat = -67802, // A symmetric key format attribute was not valid.
|
||||
MissingAttributeSymmetricKeyFormat = -67803, // A symmetric key format attribute was missing.
|
||||
InvalidAttributeWrappedKeyFormat = -67804, // A wrapped key format attribute was not valid.
|
||||
MissingAttributeWrappedKeyFormat = -67805, // A wrapped key format attribute was missing.
|
||||
StagedOperationInProgress = -67806, // A staged operation is in progress.
|
||||
StagedOperationNotStarted = -67807, // A staged operation was not started.
|
||||
VerifyFailed = -67808, // A cryptographic verification failure has occurred.
|
||||
QuerySizeUnknown = -67809, // The query size is unknown.
|
||||
BlockSizeMismatch = -67810, // A block size mismatch occurred.
|
||||
PublicKeyInconsistent = -67811, // The public key was inconsistent.
|
||||
DeviceVerifyFailed = -67812, // A device verification failure has occurred.
|
||||
InvalidLoginName = -67813, // An invalid login name was detected.
|
||||
AlreadyLoggedIn = -67814, // The user is already logged in.
|
||||
InvalidDigestAlgorithm = -67815, // An invalid digest algorithm was detected.
|
||||
InvalidCRLGroup = -67816, // An invalid CRL group was detected.
|
||||
CertificateCannotOperate = -67817, // The certificate cannot operate.
|
||||
CertificateExpired = -67818, // An expired certificate was detected.
|
||||
CertificateNotValidYet = -67819, // The certificate is not yet valid.
|
||||
CertificateRevoked = -67820, // The certificate was revoked.
|
||||
CertificateSuspended = -67821, // The certificate was suspended.
|
||||
InsufficientCredentials = -67822, // Insufficient credentials were detected.
|
||||
InvalidAction = -67823, // The action was not valid.
|
||||
InvalidAuthority = -67824, // The authority was not valid.
|
||||
VerifyActionFailed = -67825, // A verify action has failed.
|
||||
InvalidCertAuthority = -67826, // The certificate authority was not valid.
|
||||
InvalidCRLAuthority = -67827, // The CRL authority was not valid.
|
||||
InvalidCRLEncoding = -67828, // The CRL encoding was not valid.
|
||||
InvalidCRLType = -67829, // The CRL type was not valid.
|
||||
InvalidCRL = -67830, // The CRL was not valid.
|
||||
InvalidFormType = -67831, // The form type was not valid.
|
||||
InvalidID = -67832, // The ID was not valid.
|
||||
InvalidIdentifier = -67833, // The identifier was not valid.
|
||||
InvalidIndex = -67834, // The index was not valid.
|
||||
InvalidPolicyIdentifiers = -67835, // The policy identifiers are not valid.
|
||||
InvalidTimeString = -67836, // The time specified was not valid.
|
||||
InvalidReason = -67837, // The trust policy reason was not valid.
|
||||
InvalidRequestInputs = -67838, // The request inputs are not valid.
|
||||
InvalidResponseVector = -67839, // The response vector was not valid.
|
||||
InvalidStopOnPolicy = -67840, // The stop-on policy was not valid.
|
||||
InvalidTuple = -67841, // The tuple was not valid.
|
||||
MultipleValuesUnsupported = -67842, // Multiple values are not supported.
|
||||
NotTrusted = -67843, // The certificate was not trusted.
|
||||
NoDefaultAuthority = -67844, // No default authority was detected.
|
||||
RejectedForm = -67845, // The trust policy had a rejected form.
|
||||
RequestLost = -67846, // The request was lost.
|
||||
RequestRejected = -67847, // The request was rejected.
|
||||
UnsupportedAddressType = -67848, // The address type is not supported.
|
||||
UnsupportedService = -67849, // The service is not supported.
|
||||
InvalidTupleGroup = -67850, // The tuple group was not valid.
|
||||
InvalidBaseACLs = -67851, // The base ACLs are not valid.
|
||||
InvalidTupleCredentials = -67852, // The tuple credentials are not valid.
|
||||
InvalidEncoding = -67853, // The encoding was not valid.
|
||||
InvalidValidityPeriod = -67854, // The validity period was not valid.
|
||||
InvalidRequestor = -67855, // The requestor was not valid.
|
||||
RequestDescriptor = -67856, // The request descriptor was not valid.
|
||||
InvalidBundleInfo = -67857, // The bundle information was not valid.
|
||||
InvalidCRLIndex = -67858, // The CRL index was not valid.
|
||||
NoFieldValues = -67859, // No field values were detected.
|
||||
UnsupportedFieldFormat = -67860, // The field format is not supported.
|
||||
UnsupportedIndexInfo = -67861, // The index information is not supported.
|
||||
UnsupportedLocality = -67862, // The locality is not supported.
|
||||
UnsupportedNumAttributes = -67863, // The number of attributes is not supported.
|
||||
UnsupportedNumIndexes = -67864, // The number of indexes is not supported.
|
||||
UnsupportedNumRecordTypes = -67865, // The number of record types is not supported.
|
||||
FieldSpecifiedMultiple = -67866, // Too many fields were specified.
|
||||
IncompatibleFieldFormat = -67867, // The field format was incompatible.
|
||||
InvalidParsingModule = -67868, // The parsing module was not valid.
|
||||
DatabaseLocked = -67869, // The database is locked.
|
||||
DatastoreIsOpen = -67870, // The data store is open.
|
||||
MissingValue = -67871, // A missing value was detected.
|
||||
UnsupportedQueryLimits = -67872, // The query limits are not supported.
|
||||
UnsupportedNumSelectionPreds = -67873, // The number of selection predicates is not supported.
|
||||
UnsupportedOperator = -67874, // The operator is not supported.
|
||||
InvalidDBLocation = -67875, // The database location is not valid.
|
||||
InvalidAccessRequest = -67876, // The access request is not valid.
|
||||
InvalidIndexInfo = -67877, // The index information is not valid.
|
||||
InvalidNewOwner = -67878, // The new owner is not valid.
|
||||
InvalidModifyMode = -67879, // The modify mode is not valid.
|
||||
MissingRequiredExtension = -67880, // A required certificate extension is missing.
|
||||
ExtendedKeyUsageNotCritical = -67881, // The extended key usage extension was not marked critical.
|
||||
TimestampMissing = -67882, // A timestamp was expected but was not found.
|
||||
TimestampInvalid = -67883, // The timestamp was not valid.
|
||||
TimestampNotTrusted = -67884, // The timestamp was not trusted.
|
||||
TimestampServiceNotAvailable = -67885, // The timestamp service is not available.
|
||||
TimestampBadAlg = -67886, // An unrecognized or unsupported Algorithm Identifier in timestamp.
|
||||
TimestampBadRequest = -67887, // The timestamp transaction is not permitted or supported.
|
||||
TimestampBadDataFormat = -67888, // The timestamp data submitted has the wrong format.
|
||||
TimestampTimeNotAvailable = -67889, // The time source for the Timestamp Authority is not available.
|
||||
TimestampUnacceptedPolicy = -67890, // The requested policy is not supported by the Timestamp Authority.
|
||||
TimestampUnacceptedExtension = -67891, // The requested extension is not supported by the Timestamp Authority.
|
||||
TimestampAddInfoNotAvailable = -67892, // The additional information requested is not available.
|
||||
TimestampSystemFailure = -67893, // The timestamp request cannot be handled due to system failure.
|
||||
SigningTimeMissing = -67894, // A signing time was expected but was not found.
|
||||
TimestampRejection = -67895, // A timestamp transaction was rejected.
|
||||
TimestampWaiting = -67896, // A timestamp transaction is waiting.
|
||||
TimestampRevocationWarning = -67897, // A timestamp authority revocation warning was issued.
|
||||
TimestampRevocationNotification = -67898, // A timestamp authority revocation notification was issued.
|
||||
CertificatePolicyNotAllowed = -67899, // The requested policy is not allowed for this certificate.
|
||||
CertificateNameNotAllowed = -67900, // The requested name is not allowed for this certificate.
|
||||
CertificateValidityPeriodTooLong = -67901, // The validity period in the certificate exceeds the maximum allowed.
|
||||
CertificateIsCA = -67902, // The verified certificate is a CA rather than an end-entity.
|
||||
CertificateDuplicateExtension = -67903, // The certificate contains multiple extensions with the same extension ID.
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package Security
|
||||
|
||||
import CF "core:sys/darwin/CoreFoundation"
|
||||
|
||||
foreign import Security "system:Security.framework"
|
||||
|
||||
// A reference to a random number generator.
|
||||
RandomRef :: distinct rawptr
|
||||
|
||||
@(link_prefix="Sec", default_calling_convention="c")
|
||||
foreign Security {
|
||||
// Default random ref for /dev/random. Synonym for nil.
|
||||
@(link_name="kSecRandomDefault") kSecRandomDefault: RandomRef
|
||||
|
||||
// Generates an array of cryptographically secure random bytes.
|
||||
RandomCopyBytes :: proc(rnd: RandomRef = kSecRandomDefault, count: uint, bytes: [^]byte) -> errSec ---
|
||||
|
||||
CopyErrorMessageString :: proc(status: errSec, reserved: rawptr = nil) -> CF.String ---
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
//+build darwin
|
||||
package darwin
|
||||
|
||||
import "core:runtime"
|
||||
|
||||
foreign import core_foundation "system:CoreFoundation.framework"
|
||||
|
||||
CFTypeRef :: distinct rawptr
|
||||
|
||||
CFStringRef :: distinct CFTypeRef
|
||||
|
||||
CFIndex :: int
|
||||
|
||||
CFRange :: struct {
|
||||
location: CFIndex,
|
||||
length: CFIndex,
|
||||
}
|
||||
|
||||
CFStringEncoding :: enum u32 {
|
||||
ASCII = 1,
|
||||
NEXTSTEP = 2,
|
||||
JapaneseEUC = 3,
|
||||
UTF8 = 4,
|
||||
ISOLatin1 = 5,
|
||||
Symbol = 6,
|
||||
NonLossyASCII = 7,
|
||||
ShiftJIS = 8,
|
||||
ISOLatin2 = 9,
|
||||
Unicode = 10,
|
||||
WindowsCP1251 = 11,
|
||||
WindowsCP1252 = 12,
|
||||
WindowsCP1253 = 13,
|
||||
WindowsCP1254 = 14,
|
||||
WindowsCP1250 = 15,
|
||||
ISO2022JP = 21,
|
||||
MacOSRoman = 30,
|
||||
|
||||
UTF16 = Unicode,
|
||||
|
||||
UTF16BigEndian = 0x90000100,
|
||||
UTF16LittleEndian = 0x94000100,
|
||||
|
||||
UTF32 = 0x8c000100,
|
||||
UTF32BigEndian = 0x98000100,
|
||||
UTF32LittleEndian = 0x9c000100,
|
||||
}
|
||||
|
||||
foreign core_foundation {
|
||||
// Copies the character contents of a string to a local C string buffer after converting the characters to a given encoding.
|
||||
CFStringGetCString :: proc(theString: CFStringRef, buffer: [^]byte, bufferSize: CFIndex, encoding: CFStringEncoding) -> Bool ---
|
||||
|
||||
// Returns the number (in terms of UTF-16 code pairs) of Unicode characters in a string.
|
||||
CFStringGetLength :: proc(theString: CFStringRef) -> CFIndex ---
|
||||
|
||||
// Returns the maximum number of bytes a string of a specified length (in Unicode characters) will take up if encoded in a specified encoding.
|
||||
CFStringGetMaximumSizeForEncoding :: proc(length: CFIndex, encoding: CFStringEncoding) -> CFIndex ---
|
||||
|
||||
// Fetches a range of the characters from a string into a byte buffer after converting the characters to a specified encoding.
|
||||
CFStringGetBytes :: proc(
|
||||
thestring: CFStringRef,
|
||||
range: CFRange,
|
||||
encoding: CFStringEncoding,
|
||||
lossByte: u8,
|
||||
isExternalRepresentation: Bool,
|
||||
buffer: [^]byte,
|
||||
maxBufLen: CFIndex,
|
||||
usedBufLen: ^CFIndex,
|
||||
) -> CFIndex ---
|
||||
|
||||
// Releases a Core Foundation object.
|
||||
@(link_name="CFRelease")
|
||||
_CFRelease :: proc(cf: CFTypeRef) ---
|
||||
}
|
||||
|
||||
// Releases a Core Foundation object.
|
||||
CFRelease :: proc {
|
||||
CFReleaseString,
|
||||
}
|
||||
|
||||
// Releases a Core Foundation string.
|
||||
CFReleaseString :: #force_inline proc(theString: CFStringRef) {
|
||||
_CFRelease(CFTypeRef(theString))
|
||||
}
|
||||
|
||||
CFStringCopyToOdinString :: proc(theString: CFStringRef, allocator := context.allocator) -> (str: string, ok: bool) #optional_ok {
|
||||
length := CFStringGetLength(theString)
|
||||
max := CFStringGetMaximumSizeForEncoding(length, .UTF8)
|
||||
|
||||
buf, err := make([]byte, max, allocator)
|
||||
if err != nil { return }
|
||||
|
||||
raw_str := runtime.Raw_String{
|
||||
data = raw_data(buf),
|
||||
}
|
||||
CFStringGetBytes(theString, {0, length}, .UTF8, 0, false, raw_data(buf), max, &raw_str.len)
|
||||
|
||||
return transmute(string)raw_str, true
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
//+build darwin
|
||||
package darwin
|
||||
|
||||
foreign import security "system:Security.framework"
|
||||
|
||||
// A reference to a random number generator.
|
||||
SecRandomRef :: distinct rawptr
|
||||
|
||||
OSStatus :: distinct i32
|
||||
|
||||
errSec :: enum OSStatus {
|
||||
Success = 0, // No error.
|
||||
Unimplemented = -4, // Function or operation not implemented.
|
||||
|
||||
// Many more...
|
||||
}
|
||||
|
||||
foreign security {
|
||||
// Synonym for nil, uses a cryptographically secure random number generator.
|
||||
kSecRandomDefault: SecRandomRef
|
||||
|
||||
// Generates an array of cryptographically secure random bytes.
|
||||
SecRandomCopyBytes :: proc(rnd: SecRandomRef = kSecRandomDefault, count: uint, bytes: [^]byte) -> errSec ---
|
||||
|
||||
SecCopyErrorMessageString :: proc(status: errSec, reserved: rawptr = nil) -> CFStringRef ---
|
||||
}
|
||||
@@ -2074,7 +2074,13 @@ SRWLOCK_INIT :: SRWLOCK{}
|
||||
STARTF_USESTDHANDLES: DWORD : 0x00000100
|
||||
|
||||
VOLUME_NAME_DOS: DWORD : 0x0
|
||||
MOVEFILE_REPLACE_EXISTING: DWORD : 1
|
||||
|
||||
MOVEFILE_COPY_ALLOWED: DWORD: 0x2
|
||||
MOVEFILE_CREATE_HARDLINK: DWORD: 0x10
|
||||
MOVEFILE_DELAY_UNTIL_REBOOT: DWORD: 0x4
|
||||
MOVEFILE_FAIL_IF_NOT_TRACKABLE: DWORD: 0x20
|
||||
MOVEFILE_REPLACE_EXISTING: DWORD : 0x1
|
||||
MOVEFILE_WRITE_THROUGH: DWORD: 0x8
|
||||
|
||||
FILE_BEGIN: DWORD : 0
|
||||
FILE_CURRENT: DWORD : 1
|
||||
|
||||
@@ -56,9 +56,9 @@ validate_hour_minute_second :: proc "contextless" (#any_int hour, #any_int minut
|
||||
return .None
|
||||
}
|
||||
|
||||
validate_datetime :: proc "contextless" (using datetime: DateTime) -> (err: Error) {
|
||||
validate(date) or_return
|
||||
validate(time) or_return
|
||||
validate_datetime :: proc "contextless" (datetime: DateTime) -> (err: Error) {
|
||||
validate(datetime.date) or_return
|
||||
validate(datetime.time) or_return
|
||||
return .None
|
||||
}
|
||||
|
||||
@@ -69,4 +69,4 @@ validate :: proc{
|
||||
validate_hour_minute_second,
|
||||
validate_time,
|
||||
validate_datetime,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ _sleep :: proc "contextless" (d: Duration) {
|
||||
|
||||
_tick_now :: proc "contextless" () -> Tick {
|
||||
foreign odin_env {
|
||||
tick_now :: proc "contextless" () -> i64 ---
|
||||
tick_now :: proc "contextless" () -> f32 ---
|
||||
}
|
||||
return Tick{tick_now()*1e6}
|
||||
return Tick{i64(tick_now()*1e6)}
|
||||
}
|
||||
|
||||
_yield :: proc "contextless" () {
|
||||
|
||||
Reference in New Issue
Block a user