$ paint ./file.rs --style="github" --gist-like

musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
musl-wasm32.encrypt.c 58 lines1.13 KB
#include <stdint.h>
#include <stdlib.h>
struct expanded_key {
uint32_t l[16], r[16];
};
void __des_setkey(const unsigned char *key, struct expanded_key *ekey);
void __do_des(uint32_t l_in, uint32_t r_in,
uint32_t *l_out, uint32_t *r_out,
uint32_t count, uint32_t saltbits, const struct expanded_key *ekey);
static struct expanded_key __encrypt_key;
void setkey(const char *key)
{
unsigned char bkey[8];
int i, j;
for (i = 0; i < 8; i++) {
bkey[i] = 0;
for (j = 7; j >= 0; j--, key++)
bkey[i] |= (uint32_t)(*key & 1) << j;
}
__des_setkey(bkey, &__encrypt_key);
}
void encrypt(char *block, int edflag)
{
struct expanded_key decrypt_key, *key;
uint32_t b[2];
int i, j;
char *p;
p = block;
for (i = 0; i < 2; i++) {
b[i] = 0;
for (j = 31; j >= 0; j--, p++)
b[i] |= (uint32_t)(*p & 1) << j;
}
key = &__encrypt_key;
if (edflag) {
key = &decrypt_key;
for (i = 0; i < 16; i++) {
decrypt_key.l[i] = __encrypt_key.l[15-i];
decrypt_key.r[i] = __encrypt_key.r[15-i];
}
}
__do_des(b[0], b[1], b, b + 1, 1, 0, key);
p = block;
for (i = 0; i < 2; i++)
for (j = 31; j >= 0; j--)
*p++ = b[i]>>j & 1;
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
http.go 141 lines4.26 KB
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package http
import (
"io"
"strconv"
"strings"
"time"
"unicode/utf8"
"golang_org/x/net/lex/httplex"
)
// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0)
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
name string
}
func (k *contextKey) String() string { return "net/http context value " + k.name }
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
if hasPort(host) {
return strings.TrimSuffix(host, ":")
}
return host
}
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
return false
}
}
return true
}
func hexEscapeNonASCII(s string) string {
newLen := 0
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
newLen += 3
} else {
newLen++
}
}
if newLen == len(s) {
return s
}
b := make([]byte, 0, newLen)
for i := 0; i < len(s); i++ {
if s[i] >= utf8.RuneSelf {
b = append(b, '%')
b = strconv.AppendInt(b, int64(s[i]), 16)
} else {
b = append(b, s[i])
}
}
return string(b)
}
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
var (
// verify that an io.Copy from NoBody won't require a buffer:
_ io.WriterTo = NoBody
_ io.ReadCloser = NoBody
)
// PushOptions describes options for Pusher.Push.
type PushOptions struct {
// Method specifies the HTTP method for the promised request.
// If set, it must be "GET" or "HEAD". Empty means "GET".
Method string
// Header specifies additional promised request headers. This cannot
// include HTTP/2 pseudo header fields like ":path" and ":scheme",
// which will be added automatically.
Header Header
}
// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
// Push initiates an HTTP/2 server push. This constructs a synthetic
// request using the given target and options, serializes that request
// into a PUSH_PROMISE frame, then dispatches that request using the
// server's request handler. If opts is nil, default options are used.
//
// The target must either be an absolute path (like "/path") or an absolute
// URL that contains a valid host and the same scheme as the parent request.
// If the target is a path, it will inherit the scheme and host of the
// parent request.
//
// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
// Push may or may not detect these invalid pushes; however, invalid
// pushes will be detected and canceled by conforming clients.
//
// Handlers that wish to push URL X should call Push before sending any
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
}
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
index.html 76 lines3.60 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>paint demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="snippets.css" />
</head>
<body>
<div class="container">
<div class="command">
<h1>
<span class="hue-rotate">$</span> paint
./file.<span id="ext">rs</span>
<nobr>--style="<span id="style-name">github</span>"</nobr>
<nobr>--gist-like</nobr>
<nobr><span id="lines"></span></nobr>
</h1>
</div>
<div class="flex-centered">
<select id="filetype">
<option selected value="rs">rust</option>
<option value="js">javascript</option>
<option value="jsx">jsx</option>
<option value="html">html</option>
<option value="c">c</option>
<option value="py">python</option>
<option value="go">go</option>
</select>
<select id="style">
<option value="atom_dark">atom dark</option>
<option value="ayu_dark">ayu dark</option>
<option value="ayu_light">ayu light</option>
<option value="ayu_mirage">ayu mirage</option>
<option value="cobalt2">cobalt2</option>
<option value="dracula">dracula</option>
<option selected value="github">github</option>
<option value="monokai_extended">monokai extended</option>
<option value="oceanic_next">oceanic next</option>
<option value="one_dark">one dark</option>
<option value="one_light">one light</option>
<option value="one_monokai">one monokai</option>
<option value="predawn">predawn</option>
<option value="solarized_dark">solarized dark</option>
<option value="solarized_light">solarized light</option>
<option value="wombat">wombat</option>
</select>
<input id="highlight" type="checkbox" />
<label for="highlight"><nobr>--highlight</nobr></label>
</div>
<div id="highlighted" class="no-hi" data-style="github--rs" data-filetype="rs">
</div> <!-- highlighted -->
<div class="gh">
<a href="https://github.com/demille/paint">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
<span>/demille/paint</span>
</a>
</div>
</div> <!-- container -->
<div class="bg-overlay"></div>
<script src="main.js"></script>
</body>
</html>
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
rust_types.js 132 lines2.75 KB
import Struct from './Struct';
import { types, parseType, Pointer } from './types';
import { assert, vslice } from './misc';
const DATA = (typeof Symbol !== 'undefined')
? Symbol.for('struct-data')
: '__data';
function extend(StructType) {
class RustType extends StructType {
free() {
super.free(true);
}
}
Object.assign(RustType, StructType);
return RustType;
}
function RustTuple(...tupleTypes) {
const fields = {};
tupleTypes.forEach((type, i) => {
fields[i] = parseType(type);
});
return new Struct(fields);
}
function RustVector(typedef) {
const type = parseType(typedef);
const Vector = extend(new Struct({
ptr: types.pointer(type),
cap: 'usize',
len: 'usize',
/* values */
}));
Object.defineProperty(Vector.prototype, 'values', {
enumerable: true,
get() {
const arrayType = parseType([type, this.len]);
const memory = this[DATA].view.buffer;
const view = new DataView(memory, this.ptr.ref(), arrayType.width);
return arrayType.read(view, this[DATA].free);
},
set(values) {
const len = values.length;
this.ptr = new Pointer([type, len], values);
this.len = len;
this.cap = len;
},
});
return Vector;
}
function RustOption(typedef, isNonNullable = false, tagSize) {
const type = parseType(typedef);
let discriminant;
if (tagSize) discriminant = types[`uint${tagSize * 8}`];
else if (type.alignment === 1) discriminant = 'uint8';
else if (type.alignment === 2) discriminant = 'uint16';
else discriminant = 'uint32';
const fields = (isNonNullable)
? { value: type }
: { discriminant, value: type };
const Option = new Struct(fields);
Object.assign(Option.prototype, {
isSome() {
return ('discriminant' in fields) ? !!this.discriminant : !!this.value;
},
isNone() {
return !this.isSome();
},
expect(msg) {
if (!this.isSome()) throw new Error(msg);
return this.value;
},
unwrap() {
if (!this.isSome()) throw new Error('Error unwrapping none');
return this.value;
},
unwrapOr(defaultValue) {
return (this.isSome()) ? this.value : defaultValue;
},
unwrapOrElse(fn) {
return (this.isSome()) ? this.value : fn();
},
});
return Option;
}
const rust = {
tuple: RustTuple,
Tuple: (type, values) => new (RustTuple(...type))([...values]),
vector: RustVector,
Vector: (type, values) => new (RustVector(type))({ values }),
option: RustOption,
Option: (type, value, ...opts) => new (RustOption(type, ...opts))({
value,
discriminant: (typeof value === 'undefined') ? 0 : 1,
}),
Some: (...args) => rust.Option(...args),
None: (type, ...opts) => rust.Option(type, undefined, ...opts),
};
export default rust;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
app.jsx 36 lines701.00 B
import React from 'react';
import Display from './Display';
import ButtonPanel from './ButtonPanel';
import calculate from '../logic/calculate';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
total: null,
next: null,
operation: null,
};
}
handleClick = (buttonName) => {
this.setState(calculate(this.state, buttonName));
}
render() {
return (
<div className="component-app">
<Display
value={this.state.next || this.state.total || '0'}
/>
<ButtonPanel
clickHandler={this.handleClick}
/>
</div>
);
}
}
export default App;
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
middleware.http.py 41 lines1.58 KB
from django.utils.cache import (
cc_delim_re, get_conditional_response, set_response_etag,
)
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import parse_http_date_safe
class ConditionalGetMiddleware(MiddlewareMixin):
"""
Handle conditional GET operations. If the response has an ETag or
Last-Modified header and the request has If-None-Match or If-Modified-Since,
replace the response with HttpNotModified. Add an ETag header if needed.
"""
def process_response(self, request, response):
# It's too late to prevent an unsafe request with a 412 response, and
# for a HEAD request, the response body is always empty so computing
# an accurate ETag isn't possible.
if request.method != 'GET':
return response
if self.needs_etag(response) and not response.has_header('ETag'):
set_response_etag(response)
etag = response.get('ETag')
last_modified = response.get('Last-Modified')
last_modified = last_modified and parse_http_date_safe(last_modified)
if etag or last_modified:
return get_conditional_response(
request,
etag=etag,
last_modified=last_modified,
response=response,
)
return response
def needs_etag(self, response):
"""Return True if an ETag header should be added to response."""
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
return all(header.lower() != 'no-store' for header in cache_control_headers)
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
syntax_definition.rs 167 lines5.55 KB
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use onig::{Regex, RegexOptions, Region, Syntax};
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use super::scope::*;
use regex_syntax::escape;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// The main data structure representing a syntax definition loaded from a
/// `.sublime-syntax` file. You'll probably only need these as references
/// to be passed around to parsing code.
///
/// Some useful public fields are the `name` field which is a human readable
/// name to display in syntax lists, and the `hidden` field which means hide
/// this syntax from any lists because it is for internal use.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SyntaxDefinition {
pub name: String,
pub file_extensions: Vec<String>,
pub scope: Scope,
pub first_line_match: Option<String>,
pub hidden: bool,
/// Filled in at link time to avoid serializing it multiple times
#[serde(skip_serializing, skip_deserializing)]
pub prototype: Option<ContextPtr>,
#[serde(serialize_with = "ordered_map")]
pub variables: HashMap<String, String>,
#[serde(serialize_with = "ordered_map")]
pub contexts: HashMap<String, ContextPtr>,
}
impl Context {
/// Returns the match pattern at an index, panics if the thing isn't a match pattern
pub fn match_at(&self, index: usize) -> &MatchPattern {
match self.patterns[index] {
Pattern::Match(ref match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
/// Returns a mutable reference, otherwise like `match_at`
pub fn match_at_mut(&mut self, index: usize) -> &mut MatchPattern {
match self.patterns[index] {
Pattern::Match(ref mut match_pat) => match_pat,
_ => panic!("bad index to match_at"),
}
}
}
impl ContextReference {
/// find the pointed to context, panics if ref is not linked
pub fn resolve(&self) -> ContextPtr {
match *self {
ContextReference::Inline(ref ptr) => ptr.clone(),
ContextReference::Direct(ref ptr) => ptr.link.upgrade().unwrap(),
_ => panic!("Can only call resolve on linked references: {:?}", self),
}
}
}
impl MatchPattern {
/// substitutes back-refs in Regex with regions from s
/// used for match patterns which refer to captures from the pattern
/// that pushed them.
pub fn regex_with_substitutes(&self, region: &Region, s: &str) -> String {
let mut reg_str = String::new();
let mut last_was_escape = false;
for c in self.regex_str.chars() {
if last_was_escape && c.is_digit(10) {
let val = c.to_digit(10).unwrap();
if let Some((start, end)) = region.pos(val as usize) {
let escaped = escape(&s[start..end]);
reg_str.push_str(&escaped);
}
} else if last_was_escape {
reg_str.push('\\');
reg_str.push(c);
} else if c != '\\' {
reg_str.push(c);
}
last_was_escape = c == '\\' && !last_was_escape;
}
reg_str
}
/// Makes sure the regex is compiled if it doesn't have captures.
/// May compile the regex if it isn't, panicing if compilation fails.
#[inline]
pub fn ensure_compiled_if_possible(&mut self) {
if self.regex.is_none() && !self.has_captures {
self.compile_regex();
}
}
}
/// This wrapper only exists so that I can implement a serialization
/// trait that crashes if you try and serialize this.
#[derive(Debug)]
pub struct LinkerLink {
pub link: Weak<RefCell<Context>>,
}
impl Eq for LinkerLink {}
impl PartialEq for LinkerLink {
fn eq(&self, other: &LinkerLink) -> bool {
self.link.upgrade() == other.link.upgrade()
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl Serialize for LinkerLink {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error> where S: Serializer {
panic!("Can't serialize syntax definitions which have been linked");
}
}
/// Just panics, we can't do anything with linked up syntaxes
impl<'de> Deserialize<'de> for LinkerLink {
fn deserialize<D>(_: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
panic!("No linked syntax should ever have gotten serialized");
}
}
/// Serialize the provided map in natural key order, so that it's deterministic when dumping.
fn ordered_map<K, V, S>(map: &HashMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, K: Eq + Hash + Ord + Serialize, V: Serialize
{
let ordered: BTreeMap<_, _> = map.iter().collect();
ordered.serialize(serializer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_compile_refs() {
use onig::{SearchOptions, Regex, Region};
let pat = MatchPattern {
has_captures: true,
regex_str: String::from(r"lol \\ \2 \1 '\9' \wz"),
regex: None,
scope: vec![],
captures: None,
operation: MatchOperation::None,
with_prototype: None,
};
let r = Regex::new(r"(\\\[\]\(\))(b)(c)(d)(e)").unwrap();
let mut region = Region::new();
let s = r"\[]()bcde";
assert!(r.match_with_options(s, 0, SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)).is_some());
let regex_res = pat.regex_with_substitutes(&region, s);
assert_eq!(regex_res, r"lol \\ b \\\[\]\(\) '' \wz");
pat.compile_with_refs(&region, s);
}
}
/demille/paint