Initial checkin

This commit is contained in:
Winni Neessen 2024-09-01 16:01:58 +02:00
parent f3a9441638
commit 03f6fd14d1
Signed by: wneessen
GPG key ID: 385AC9889632126E
10 changed files with 269 additions and 1 deletions

6
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,6 @@
# SPDX-FileCopyrightText: 2023 Winni Neessen <wn@neessen.dev>
#
# SPDX-License-Identifier: CC0-1.0
github: wneessen
ko_fi: winni

39
.github/workflows/codecov.yml vendored Normal file
View file

@ -0,0 +1,39 @@
# SPDX-FileCopyrightText: 2024 Winni Neessen <wn@neessen.dev>
#
# SPDX-License-Identifier: CC0-1.0
name: Codecov workflow
on:
push:
branches:
- main
paths:
- '**.go'
- 'go.*'
- '.forgejo/**'
- 'codecov.yml'
pull_request:
branches:
- main
paths:
- '**.go'
- 'go.*'
- '.forgejo/**'
- 'codecov.yml'
jobs:
run:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@master
- name: Setup go
uses: actions/setup-go@v4
with:
go-version: '1.23'
- name: Run Tests
run: |
go test -v -shuffle=on -race --coverprofile=coverage.coverprofile --covermode=atomic ./...
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos

49
.github/workflows/golangci-lint.yml vendored Normal file
View file

@ -0,0 +1,49 @@
# SPDX-FileCopyrightText: 2024 Winni Neessen <wn@neessen.dev>
#
# SPDX-License-Identifier: CC0-1.0
name: golangci-lint
on:
push:
tags:
- v*
branches:
- main
pull_request:
permissions:
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
# pull-requests: read
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v4
with:
go-version: '1.23'
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: latest
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true
# Optional: if set to true then the all caching functionality will be complete disabled,
# takes precedence over all other caching options.
# skip-cache: true
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
# skip-pkg-cache: true
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
# skip-build-cache: true

15
.github/workflows/reuse.yml vendored Normal file
View file

@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2024 Winni Neessen <wn@neessen.dev>
#
# SPDX-License-Identifier: CC0-1.0
name: REUSE Compliance Check
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v1

1
.gitignore vendored
View file

@ -23,3 +23,4 @@ go.work.sum
# env file # env file
.env .env
.idea/

14
.golangci.toml Normal file
View file

@ -0,0 +1,14 @@
## SPDX-FileCopyrightText: 2022 Winni Neessen <wn@neessen.dev>
##
## SPDX-License-Identifier: MIT
[run]
go = "1.20"
tests = true
[linters]
enable = ["stylecheck", "whitespace", "containedctx", "contextcheck", "decorder",
"errname", "errorlint", "gofmt", "gofumpt", "goimports"]
[linters-settings.goimports]
local-prefixes = "github.com/wneessen/niljson"

View file

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2024 Winni Neessen Copyright (c) 2024 Winni Neessen <wn@neessen.dev>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

7
go.mod Normal file
View file

@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: 2024 Winni Neessen <wn@neessen.dev>
//
// SPDX-License-Identifier: MIT
module github.com/wneessen/niljson
go 1.23

60
niljson.go Normal file
View file

@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: 2024 Winni Neessen <wn@neessen.dev>
//
// SPDX-License-Identifier: MIT
package niljson
import "encoding/json"
// Variable is a generic variable type that can be null.
type Variable[T any] struct {
value T
notNil bool
}
// Get the value of the Variable
func (v *Variable[T]) Get() T {
return v.value
}
// NotNil returns true when a Variable is not nil
func (v *Variable[T]) NotNil() bool {
return v.notNil
}
// IsNil returns true when a Variable is nil
func (v *Variable[T]) IsNil() bool {
return !v.notNil
}
// Reset resets the value to the Variable to a zero value and sets it to be nil
func (v *Variable[T]) Reset() {
var newVal T
v.value = newVal
v.notNil = false
}
// NilBoolean is an boolean type that can be nil
type NilBoolean = Variable[bool]
// NilInt is an int type that can be nil
type NilInt = Variable[int]
// NilInt64 is an int64 type that can be nil
type NilInt64 = Variable[int64]
// NilFloat64 is an float64 type that can be nil
type NilFloat64 = Variable[float64]
// NilString is a string type that can be nil
type NilString = Variable[string]
// UnmarshalJSON interprets the generic Nil types and sets the value and notnil of the type
func (v *Variable[T]) UnmarshalJSON(data []byte) error {
if string(data) != "null" {
v.value = *new(T)
v.notNil = true
return json.Unmarshal(data, &v.value)
}
return nil
}

77
niljson_test.go Normal file
View file

@ -0,0 +1,77 @@
// SPDX-FileCopyrightText: 2024 Winni Neessen <wn@neessen.dev>
//
// SPDX-License-Identifier: MIT
package niljson
import (
"encoding/json"
"testing"
)
func TestVariable_UnmarshalJSON(t *testing.T) {
jsonBytes := []byte(`{"string":"test", "int":123, "int64": 12345678901234, "float":123.456, "nil":null, "bool":true}`)
type JSONType struct {
Bool NilBoolean `json:"bool"`
Float64 NilFloat64 `json:"float"`
Int NilInt `json:"int"`
Int64 NilInt64 `json:"int64"`
NullString NilString `json:"nil"`
String NilString `json:"string"`
}
var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf("failed to unmarshal json with nil types: %v", err)
}
if jt.Float64.IsNil() {
t.Errorf("expected not nil float64")
}
if jt.Int.IsNil() {
t.Errorf("expected not nil int")
}
if jt.Int64.IsNil() {
t.Errorf("expected not nil int64")
}
if jt.String.IsNil() {
t.Errorf("expected not nil string")
}
if jt.NullString.NotNil() {
t.Errorf("expected nil string")
}
if !jt.Bool.Get() {
t.Errorf("expected bool to be true, got %t", jt.Bool.Get())
}
if jt.Float64.Get() != 123.456 {
t.Errorf("expected float64 to be 123.456, got %f", jt.Float64.Get())
}
if jt.Int.Get() != 123 {
t.Errorf("expected int to be 123, got %d", jt.Int.Get())
}
if jt.Int64.Get() != 12345678901234 {
t.Errorf("expected int to be 12345678901234, got %d", jt.Int64.Get())
}
if jt.String.Get() != "test" {
t.Errorf("expected string to be 'test', got %s", jt.String.Get())
}
jt.Bool.Reset()
if jt.Bool.NotNil() {
t.Errorf("expected bool to be nil after reset")
}
jt.Float64.Reset()
if jt.Float64.NotNil() {
t.Errorf("expected float64 to be nil after reset")
}
jt.Int.Reset()
if jt.Int.NotNil() {
t.Errorf("expected int to be nil after reset")
}
jt.Int64.Reset()
if jt.Int64.NotNil() {
t.Errorf("expected int64 to be nil after reset")
}
jt.String.Reset()
if jt.String.NotNil() {
t.Errorf("expected string to be nil after reset")
}
}