Skip to content

Commit 39ef9b2

Browse files
authored
time: implement faster and simpler push_http_header (#26155)
1 parent 8f2a3d7 commit 39ef9b2

3 files changed

Lines changed: 53 additions & 14 deletions

File tree

vlib/builtin/js/array.js.v

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ pub fn (a array) to_number_array() JS.Array {
414414
return tmp
415415
}
416416

417+
// push_many - appends multiple values to the end of the array.
418+
pub fn (mut a array) push_many(val voidptr, size int) {
419+
a.insert_many(a.len, val, size)
420+
}
421+
417422
type EveryFn = fn (JS.Number, JS.Number) JS.Boolean
418423

419424
type BigEveryFn = fn (JS.BigInt, JS.Number) JS.Boolean

vlib/time/format.v

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,28 @@ fn int_to_byte_array_no_pad(value int, mut arr []u8, size int) {
3535
}
3636
}
3737

38+
// int_to_byte_array_no_pad fulfill buffer by part
39+
// it doesn't pad with leading zeros for performance reasons
40+
@[direct_array_access; unsafe]
41+
fn int_to_ptr_byte_array_no_pad(value int, arr_prt &u8, arr_len int) {
42+
mut num := value
43+
if arr_len <= 0 || num < 0 {
44+
return
45+
}
46+
47+
// Start from the end of the array
48+
mut i := arr_len - 1
49+
50+
// Convert each digit to a character and store it in the array
51+
for num > 0 && i >= 0 {
52+
unsafe {
53+
*(arr_prt + i) = (num % 10) + `0`
54+
}
55+
num /= 10
56+
i--
57+
}
58+
}
59+
3860
// format returns a date string in "YYYY-MM-DD HH:mm" format (24h).
3961
@[manualfree]
4062
pub fn (t Time) format() string {
@@ -698,26 +720,31 @@ pub fn (t Time) utc_string() string {
698720
// e.g. "Sun, 06 Nov 1994 08:49:37 GMT"
699721
@[manualfree]
700722
pub fn (t Time) http_header_string() string {
723+
mut buf := []u8{cap: 29}
724+
t.push_to_http_header(mut buf)
725+
726+
return buf.bytestr()
727+
}
728+
729+
// push_to_http_header returns a date string in the format used in HTTP headers, as defined in RFC 2616.
730+
// e.g. "Sun, 06 Nov 1994 08:49:37 GMT"
731+
pub fn (t Time) push_to_http_header(mut buffer []u8) {
701732
day_str := t.weekday_str()
702733
month_str := t.smonth()
703734

704735
mut buf := [day_str[0], day_str[1], day_str[2], `,`, ` `, `0`, `0`, ` `, month_str[0], month_str[1],
705736
month_str[2], ` `, `0`, `0`, `0`, `0`, ` `, `0`, `0`, `:`, `0`, `0`, `:`, `0`, `0`, ` `,
706-
`G`, `M`, `T`]
707-
708-
defer {
709-
unsafe { buf.free() }
737+
`G`, `M`, `T`]!
738+
unsafe {
739+
int_to_ptr_byte_array_no_pad(t.day, &buf[5], 2)
740+
int_to_ptr_byte_array_no_pad(t.year, &buf[12], 4)
741+
int_to_ptr_byte_array_no_pad(t.hour, &buf[17], 2)
742+
int_to_ptr_byte_array_no_pad(t.minute, &buf[20], 2)
743+
int_to_ptr_byte_array_no_pad(t.second, &buf[23], 2)
744+
}
745+
unsafe {
746+
buffer.push_many(&buf[0], buf.len)
710747
}
711-
712-
int_to_byte_array_no_pad(t.day, mut buf, 7)
713-
int_to_byte_array_no_pad(t.year, mut buf, 16)
714-
int_to_byte_array_no_pad(t.hour, mut buf, 19)
715-
int_to_byte_array_no_pad(t.minute, mut buf, 22)
716-
int_to_byte_array_no_pad(t.second, mut buf, 25)
717-
718-
http_header_string := buf.bytestr()
719-
720-
return http_header_string
721748
}
722749

723750
// mceil returns the least integer value greater than or equal to x.

vlib/time/time_format_test.v

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,10 @@ fn test_utc_string() {
8989
fn test_http_header_string() {
9090
assert 'Fri, 11 Jul 1980 21:23:42 GMT' == time_to_test.http_header_string()
9191
}
92+
93+
fn test_push_to_http_header() {
94+
mut http1_1_buffer := 'HTTP/1.1 200 OK\r\nDate: '.bytes()
95+
time_to_test.push_to_http_header(mut http1_1_buffer)
96+
97+
assert http1_1_buffer.bytestr() == 'HTTP/1.1 200 OK\r\nDate: Fri, 11 Jul 1980 21:23:42 GMT'
98+
}

0 commit comments

Comments
 (0)