Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@ on: [ pull_request ]

jobs:
compliant:
runs-on: [ self-hosted, X64 ]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6

- name: Check License Header
uses: apache/skywalking-eyes/header@v0.4.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Check Spell
uses: crate-ci/typos@master
uses: crate-ci/typos@master

staticcheck:
runs-on: [ self-hosted, X64 ]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v6
with:
go-version: 1.20
go-version: "1.20.x"

- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ~/go/pkg/mod
key: reviewdog-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
Expand All @@ -46,13 +46,13 @@ jobs:

# not ready: unknown issue related to the env, skip for now
# lint:
# runs-on: [ self-hosted, X64 ]
# runs-on: ubuntu-24.04
# steps:
# - uses: actions/checkout@v3
# - uses: actions/checkout@v6
# - name: Set up Go
# uses: actions/setup-go@v3
# uses: actions/setup-go@v6
# with:
# go-version: 1.20
# go-version: "1.20.x"

# - name: Golangci Lint
# # https://golangci-lint.run/
Expand Down
45 changes: 41 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ jobs:
strategy:
matrix:
go: [ 1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x, 1.23.x]
os: [ X64 ]
runs-on: ${{ matrix.os }}
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6

- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go }}

Expand All @@ -22,3 +21,41 @@ jobs:

- name: Benchmark
run: cd ./bench && go test -bench=. -benchmem -run=none ./...

fallback-test:
strategy:
fail-fast: false
matrix:
include:
- name: ubuntu-x86 noasm
go: 1.20.x
os: ubuntu-24.04
command: go test -tags noasm .
- name: ubuntu-x86 appengine
go: 1.20.x
os: ubuntu-24.04
command: go test -tags appengine .
- name: macos arm64
go: 1.20.x
os: macos-14
command: go test .
- name: ubuntu arm64
go: 1.20.x
os: ubuntu-24.04-arm
command: go test .
- name: riscv64 compile
go: 1.20.x
os: ubuntu-24.04
command: GOOS=linux GOARCH=riscv64 CGO_ENABLED=0 go test -run '^$' -exec=/usr/bin/true .
name: Fallback Test (${{ matrix.name }})
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go }}

- name: Test fallback path
run: ${{ matrix.command }}
12 changes: 12 additions & 0 deletions _typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,15 @@

[files]
extend-exclude = ["go.mod", "go.sum", "check_branch_name.sh"]

[default.extend-words]
asure = "asure"
brillig = "brillig"
easure = "easure"
fo = "fo"
leasure = "leasure"
shll = "shll"
slithy = "slithy"
sur = "sur"
toves = "toves"
Twas = "Twas"
102 changes: 46 additions & 56 deletions base64x.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@

package base64x

import (
`encoding/base64`

"github.com/cloudwego/base64x/internal/native"
)

// An Encoding is a radix 64 encoding/decoding scheme, defined by a
// 64-character alphabet. The most common encoding is the "base64"
// encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM
Expand All @@ -30,10 +24,10 @@ import (
type Encoding int

const (
_MODE_URL = 1 << 0
_MODE_RAW = 1 << 1
_MODE_AVX2 = 1 << 2
_MODE_JSON = 1 << 3
_MODE_URL = 1 << 0
_MODE_RAW = 1 << 1
_MODE_AVX2 = 1 << 2
_MODE_JSON = 1 << 3
)

// StdEncoding is the standard base64 encoding, as defined in
Expand All @@ -57,10 +51,10 @@ const RawStdEncoding Encoding = _MODE_RAW
const RawURLEncoding Encoding = _MODE_RAW | _MODE_URL

// JSONStdEncoding is the StdEncoding and encoded as JSON string as RFC 8259.
const JSONStdEncoding Encoding = _MODE_JSON;
const JSONStdEncoding Encoding = _MODE_JSON

var (
archFlags = 0
archFlags = 0
)

/** Encoder Functions **/
Expand All @@ -75,41 +69,41 @@ var (
// If out is not large enough to contain the encoded result,
// it will panic.
func (self Encoding) Encode(out []byte, src []byte) {
if len(src) != 0 {
if buf := out[:0:len(out)]; self.EncodedLen(len(src)) <= len(out) {
self.EncodeUnsafe(&buf, src)
} else {
panic("encoder output buffer is too small")
}
}
if len(src) != 0 {
if buf := out[:0:len(out)]; self.EncodedLen(len(src)) <= len(out) {
self.EncodeUnsafe(&buf, src)
} else {
panic("encoder output buffer is too small")
}
}
}

// EncodeUnsafe behaves like Encode, except it does NOT check if
// out is large enough to contain the encoded result.
//
// It will also update the length of out.
func (self Encoding) EncodeUnsafe(out *[]byte, src []byte) {
native.B64Encode(out, &src, int(self) | archFlags)
encode(out, src, int(self)|archFlags)
}

// EncodeToString returns the base64 encoding of src.
func (self Encoding) EncodeToString(src []byte) string {
nbs := len(src)
ret := make([]byte, 0, self.EncodedLen(nbs))
nbs := len(src)
ret := make([]byte, 0, self.EncodedLen(nbs))

/* encode in native code */
self.EncodeUnsafe(&ret, src)
return mem2str(ret)
/* encode in native code */
self.EncodeUnsafe(&ret, src)
return mem2str(ret)
}

// EncodedLen returns the length in bytes of the base64 encoding
// of an input buffer of length n.
func (self Encoding) EncodedLen(n int) int {
if (self & _MODE_RAW) == 0 {
return (n + 2) / 3 * 4
} else {
return (n * 8 + 5) / 6
}
if (self & _MODE_RAW) == 0 {
return (n + 2) / 3 * 4
} else {
return (n*8 + 5) / 6
}
}

/** Decoder Functions **/
Expand All @@ -124,46 +118,42 @@ func (self Encoding) EncodedLen(n int) int {
// If out is not large enough to contain the encoded result,
// it will panic.
func (self Encoding) Decode(out []byte, src []byte) (int, error) {
if len(src) == 0 {
return 0, nil
} else if buf := out[:0:len(out)]; self.DecodedLen(len(src)) <= len(out) {
return self.DecodeUnsafe(&buf, src)
} else {
panic("decoder output buffer is too small")
}
if len(src) == 0 {
return 0, nil
} else if buf := out[:0:len(out)]; self.DecodedLen(len(src)) <= len(out) {
return self.DecodeUnsafe(&buf, src)
} else {
panic("decoder output buffer is too small")
}
}

// DecodeUnsafe behaves like Decode, except it does NOT check if
// out is large enough to contain the decoded result.
//
// It will also update the length of out.
func (self Encoding) DecodeUnsafe(out *[]byte, src []byte) (int, error) {
if n := native.B64Decode(out, mem2addr(src), len(src), int(self) | archFlags); n >= 0 {
return n, nil
} else {
return 0, base64.CorruptInputError(-n - 1)
}
return decode(out, src, int(self)|archFlags)
}

// DecodeString returns the bytes represented by the base64 string s.
func (self Encoding) DecodeString(s string) ([]byte, error) {
src := str2mem(s)
ret := make([]byte, 0, self.DecodedLen(len(s)))

/* decode into the allocated buffer */
if _, err := self.DecodeUnsafe(&ret, src); err != nil {
return nil, err
} else {
return ret, nil
}
src := str2mem(s)
ret := make([]byte, 0, self.DecodedLen(len(s)))

/* decode into the allocated buffer */
if _, err := self.DecodeUnsafe(&ret, src); err != nil {
return nil, err
} else {
return ret, nil
}
}

// DecodedLen returns the maximum length in bytes of the decoded data
// corresponding to n bytes of base64-encoded data.
func (self Encoding) DecodedLen(n int) int {
if (self & _MODE_RAW) == 0 {
return n / 4 * 3
} else {
return n * 6 / 8
}
if (self & _MODE_RAW) == 0 {
return n / 4 * 3
} else {
return n * 6 / 8
}
}
24 changes: 24 additions & 0 deletions base64x_error_native_amd64_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2024 CloudWeGo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build amd64 && !noasm && !appengine
// +build amd64,!noasm,!appengine

package base64x

import "encoding/base64"

func missingPaddingDecodeError() base64.CorruptInputError {
return base64.CorruptInputError(6)
}
Loading
Loading