<commit_before>package tau

import (
	"fmt"
	"log"
	"testing"
	"time"
)

type TestTime struct {
	time.Time
	current time.Time
}

func (tt TestTime) Since() Tau {
	return Tau(tt.current.Sub(tt.Time) / 1e9)
}

func (tt TestTime) AddTau(t Tau) Time {
	return TestTime{
		Time:    tt.Time.Add(time.Duration(t) * time.Second),
		current: tt.current,
	}
}

// newTestTime creates a deterministic TestTime for given value and current time.
func newTestTime(current, value string) TestTime {
	layout := "2006-01-02 15:04" // a simple time layout
	parse := func(s string) time.Time {
		t, err := time.Parse(layout, s)
		if err != nil {
			log.Fatalf("got err: %v\n", err)
		}
		return t
	}
	return TestTime{
		Time:    parse(value),
		current: parse(current),
	}
}

func TestTau(t *testing.T) {
	cases := []struct {
		in   Time
		want Tau
	}{
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-29 12:00"),
			want: Tau(0),
		},
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-17 22:14"),
			want: Tau(999960),
		},
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-17 22:13"),
			want: Tau(1000020),
		},
		{
			in:   newTestTime("2016-11-26 16:47", "1985-03-20 15:00"),
			want: Tau(1000000020),
		},
		{
			in:   newTestTime("2019-03-10 18:34", "1955-10-24 15:00"),
			want: Tau(2000000040),
		},
	}

	for i, tt := range cases {
		out := TauSince(tt.in)
		if tt.want != out {
			t.Errorf("[%d] TauSince(%v) => %v; want %v\n", i, tt.in, out, tt.want)
		}
	}
}

func TestMegaTau(t *testing.T) {
	cases := []struct {
		in   Time
		want MegaTau
	}{
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-29 12:00"),
			want: MegaTau(0),
		},
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-17 22:14"),
			want: MegaTau(0),
		},
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-17 22:13"),
			want: MegaTau(1),
		},
		{
			in:   newTestTime("2016-11-26 16:46", "1985-03-20 15:00"),
			want: MegaTau(999),
		},
		{
			in:   newTestTime("2015-05-09 09:00", "1985-03-20 15:00"),
			want: MegaTau(950),
		},
		{
			in:   newTestTime("2016-11-26 16:47", "1985-03-20 15:00"),
			want: MegaTau(1000),
		},
		{
			in:   newTestTime("2018-06-30 12:00", "1985-03-20 15:00"),
			want: MegaTau(1050),
		},
		{
			in:   newTestTime("2014-12-03 17:47", "1983-03-27 15:00"),
			want: MegaTau(1000),
		},
		{
			in:   newTestTime("2016-07-04 12:00", "1983-03-27 15:00"),
			want: MegaTau(1050),
		},
		{
			in:   newTestTime("2018-02-03 12:00", "1983-03-27 15:00"),
			want: MegaTau(1100),
		},
		{
			in:   newTestTime("2015-06-26 15:00", "1985-03-20 15:00"),
			want: MegaTau(955),
		},
		{
			// TODO(hkjn): This is the largest time span that can be
			// represented with time.Duration. Add more test cases once this
			// limitation is removed.
			in:   newTestTime("2277-06-25 07:26", "1985-03-20 15:00"),
			want: MegaTau(9222),
		},
	}
	for i, tt := range cases {
		out := TauSince(tt.in).Mega()
		if tt.want != out {
			t.Errorf("[%d] TauSince(%v).Mega() => %v; want %v\n", i, tt.in, out, tt.want)
		}
	}
}

func TestGigaTau(t *testing.T) {
	cases := []struct {
		in   Time
		want GigaTau
	}{
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-29 12:00"),
			want: GigaTau(0),
		},
		{
			in:   newTestTime("2016-11-26 16:46", "1985-03-20 15:00"),
			want: GigaTau(0),
		},
		{
			in:   newTestTime("2016-11-26 16:47", "1985-03-20 15:00"),
			want: GigaTau(1),
		},
		{
			in:   newTestTime("2019-03-10 18:34", "1955-10-24 15:00"),
			want: GigaTau(2),
		},
		{
			in:   newTestTime("2277-06-25 07:26", "1985-03-20 15:00"),
			want: GigaTau(9),
		},
	}
	for i, tt := range cases {
		out := TauSince(tt.in).Giga()
		if tt.want != out {
			t.Errorf("[%d] TauSince(%v).Giga() => %v; want %v\n", i, tt.in, out, tt.want)
		}
	}
}

func TestAddTau(t *testing.T) {
	type in struct {
		time Time
		tau  Tau
	}
	cases := []struct {
		in   in
		want Tau
	}{
		{
			in: in{
				time: newTestTime("2015-06-29 12:00", "2015-06-29 12:00"),
				tau:  Tau(0),
			},
			want: Tau(0),
		},
		{
			in: in{
				time: newTestTime("2015-06-29 12:00", "2015-06-29 11:59"),
				tau:  Tau(0),
			},
			want: Tau(60),
		},
		{
			in: in{
				time: newTestTime("2015-06-29 12:00", "2015-06-29 12:01"),
				tau:  Tau(0),
			},
			want: Tau(-60),
		},
		{
			in: in{
				time: newTestTime("2016-11-26 16:47", "1985-03-20 15:00"),
				tau:  Tau(0),
			},
			want: Tau(1000000020),
		},
		{
			in: in{
				time: newTestTime("2016-11-26 16:47", "1985-03-20 15:00"),
				tau:  Tau(1000),
			},
			want: Tau(999999020),
		},
		{
			in: in{
				time: newTestTime("2016-11-26 16:47", "2017-01-01 12:00"),
				tau:  Tau(0),
			},
			want: Tau(-3093180),
		},
		{
			in: in{
				time: newTestTime("2016-03-30 06:37", "2016-03-30 06:37"),
				tau:  Tau(1000000),
			},
			want: Tau(-1000000),
		},
	}

	for i, tt := range cases {
		got := tt.in.time.AddTau(tt.in.tau).Since()
		if tt.want != got {
			t.Errorf("[%d] TauSince(%v).AddTau(%v).Since() => %v; want %v\n", i, tt.in.time, tt.in.tau, got, tt.want)
		}
	}
}

func ExampleClockTime_AddTau() {
	layout := "2006-01-02 15:04" // a simple time layout
	parse := func(s string) time.Time {
		t, err := time.Parse(layout, s)
		if err != nil {
			log.Fatalf("got err: %v\n", err)
		}
		return t
	}
	t0 := ClockTime(parse("1985-03-20 15:00"))
	fmt.Printf("Time t0 is %v\n", t0)
	for mt := 900; mt <= 1200; mt += 50 {
		t1 := t0.AddTau(MegaTau(mt).Tau())
		fmt.Printf("After %d mt: %v\n", mt, t1)
	}

	t1 := t0.AddTau(MegaTau(950).Tau())
	fmt.Printf("Time t1 is %v\n", t1)
	for mt := 1; mt <= 5; mt += 1 {
		t2 := t1.AddTau(MegaTau(mt).Tau())
		fmt.Printf("[%d] After %d mt: %v\n", 950+mt, mt, t2)
	}
	// Output: Time t0 is 1985-03-20 15:00:00 +0000 UTC
	// After 900 mt: 2013-09-26 07:00:00 +0000 UTC
	// After 950 mt: 2015-04-27 23:53:20 +0000 UTC
	// After 1000 mt: 2016-11-26 16:46:40 +0000 UTC
	// After 1050 mt: 2018-06-28 09:40:00 +0000 UTC
	// After 1100 mt: 2020-01-28 02:33:20 +0000 UTC
	// After 1150 mt: 2021-08-28 19:26:40 +0000 UTC
	// After 1200 mt: 2023-03-30 12:20:00 +0000 UTC
	// Time t1 is 2015-04-27 23:53:20 +0000 UTC
	// [951] After 1 mt: 2015-05-09 13:40:00 +0000 UTC
	// [952] After 2 mt: 2015-05-21 03:26:40 +0000 UTC
	// [953] After 3 mt: 2015-06-01 17:13:20 +0000 UTC
	// [954] After 4 mt: 2015-06-13 07:00:00 +0000 UTC
	// [955] After 5 mt: 2015-06-24 20:46:40 +0000 UTC
}
<commit_msg>Add test<commit_after>package tau

import (
	"fmt"
	"log"
	"testing"
	"time"
)

type TestTime struct {
	time.Time
	current time.Time
}

func (tt TestTime) Since() Tau {
	return Tau(tt.current.Sub(tt.Time) / 1e9)
}

func (tt TestTime) AddTau(t Tau) Time {
	return TestTime{
		Time:    tt.Time.Add(time.Duration(t) * time.Second),
		current: tt.current,
	}
}

// newTestTime creates a deterministic TestTime for given value and current time.
func newTestTime(current, value string) TestTime {
	layout := "2006-01-02 15:04" // a simple time layout
	parse := func(s string) time.Time {
		t, err := time.Parse(layout, s)
		if err != nil {
			log.Fatalf("got err: %v\n", err)
		}
		return t
	}
	return TestTime{
		Time:    parse(value),
		current: parse(current),
	}
}

func TestTau(t *testing.T) {
	cases := []struct {
		in   Time
		want Tau
	}{
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-29 12:00"),
			want: Tau(0),
		},
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-17 22:14"),
			want: Tau(999960),
		},
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-17 22:13"),
			want: Tau(1000020),
		},
		{
			in:   newTestTime("2016-11-26 16:47", "1985-03-20 15:00"),
			want: Tau(1000000020),
		},
		{
			in:   newTestTime("2019-03-10 18:34", "1955-10-24 15:00"),
			want: Tau(2000000040),
		},
	}

	for i, tt := range cases {
		out := TauSince(tt.in)
		if tt.want != out {
			t.Errorf("[%d] TauSince(%v) => %v; want %v\n", i, tt.in, out, tt.want)
		}
	}
}

func TestMegaTau(t *testing.T) {
	cases := []struct {
		in   Time
		want MegaTau
	}{
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-29 12:00"),
			want: MegaTau(0),
		},
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-17 22:14"),
			want: MegaTau(0),
		},
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-17 22:13"),
			want: MegaTau(1),
		},
		{
			in:   newTestTime("2016-11-26 16:46", "1985-03-20 15:00"),
			want: MegaTau(999),
		},
		{
			in:   newTestTime("2015-05-09 09:00", "1985-03-20 15:00"),
			want: MegaTau(950),
		},
		{
			in:   newTestTime("2016-11-26 16:47", "1985-03-20 15:00"),
			want: MegaTau(1000),
		},
		{
			in:   newTestTime("2018-06-30 12:00", "1985-03-20 15:00"),
			want: MegaTau(1050),
		},
		{
			in:   newTestTime("2014-12-03 17:47", "1983-03-27 15:00"),
			want: MegaTau(1000),
		},
		{
			in:   newTestTime("2016-07-04 12:00", "1983-03-27 15:00"),
			want: MegaTau(1050),
		},
		{
			in:   newTestTime("2018-02-03 12:00", "1983-03-27 15:00"),
			want: MegaTau(1100),
		},
		{
			in:   newTestTime("2015-06-26 15:00", "1985-03-20 15:00"),
			want: MegaTau(955),
		},
		{
			// TODO(hkjn): This is the largest time span that can be
			// represented with time.Duration. Add more test cases once this
			// limitation is removed.
			in:   newTestTime("2277-06-25 07:26", "1985-03-20 15:00"),
			want: MegaTau(9222),
		},
	}
	for i, tt := range cases {
		out := TauSince(tt.in).Mega()
		if tt.want != out {
			t.Errorf("[%d] TauSince(%v).Mega() => %v; want %v\n", i, tt.in, out, tt.want)
		}
	}
}

func TestGigaTau(t *testing.T) {
	cases := []struct {
		in   Time
		want GigaTau
	}{
		{
			in:   newTestTime("2015-06-29 12:00", "2015-06-29 12:00"),
			want: GigaTau(0),
		},
		{
			in:   newTestTime("2016-11-26 16:46", "1985-03-20 15:00"),
			want: GigaTau(0),
		},
		{
			in:   newTestTime("2016-11-26 16:47", "1985-03-20 15:00"),
			want: GigaTau(1),
		},
		{
			in:   newTestTime("2019-03-10 19:00", "1955-10-24 15:00"),
			want: GigaTau(2),
		},
		{
			in:   newTestTime("2019-03-10 18:34", "1955-10-24 15:00"),
			want: GigaTau(2),
		},
		{
			in:   newTestTime("2277-06-25 07:26", "1985-03-20 15:00"),
			want: GigaTau(9),
		},
	}
	for i, tt := range cases {
		out := TauSince(tt.in).Giga()
		if tt.want != out {
			t.Errorf("[%d] TauSince(%v).Giga() => %v; want %v\n", i, tt.in, out, tt.want)
		}
	}
}

func TestAddTau(t *testing.T) {
	type in struct {
		time Time
		tau  Tau
	}
	cases := []struct {
		in   in
		want Tau
	}{
		{
			in: in{
				time: newTestTime("2015-06-29 12:00", "2015-06-29 12:00"),
				tau:  Tau(0),
			},
			want: Tau(0),
		},
		{
			in: in{
				time: newTestTime("2015-06-29 12:00", "2015-06-29 11:59"),
				tau:  Tau(0),
			},
			want: Tau(60),
		},
		{
			in: in{
				time: newTestTime("2015-06-29 12:00", "2015-06-29 12:01"),
				tau:  Tau(0),
			},
			want: Tau(-60),
		},
		{
			in: in{
				time: newTestTime("2016-11-26 16:47", "1985-03-20 15:00"),
				tau:  Tau(0),
			},
			want: Tau(1000000020),
		},
		{
			in: in{
				time: newTestTime("2016-11-26 16:47", "1985-03-20 15:00"),
				tau:  Tau(1000),
			},
			want: Tau(999999020),
		},
		{
			in: in{
				time: newTestTime("2016-11-26 16:47", "2017-01-01 12:00"),
				tau:  Tau(0),
			},
			want: Tau(-3093180),
		},
		{
			in: in{
				time: newTestTime("2016-03-30 06:37", "2016-03-30 06:37"),
				tau:  Tau(1000000),
			},
			want: Tau(-1000000),
		},
	}

	for i, tt := range cases {
		got := tt.in.time.AddTau(tt.in.tau).Since()
		if tt.want != got {
			t.Errorf("[%d] TauSince(%v).AddTau(%v).Since() => %v; want %v\n", i, tt.in.time, tt.in.tau, got, tt.want)
		}
	}
}

func ExampleClockTime_AddTau() {
	layout := "2006-01-02 15:04" // a simple time layout
	parse := func(s string) time.Time {
		t, err := time.Parse(layout, s)
		if err != nil {
			log.Fatalf("got err: %v\n", err)
		}
		return t
	}
	t0 := ClockTime(parse("1985-03-20 15:00"))
	fmt.Printf("Time t0 is %v\n", t0)
	for mt := 900; mt <= 1200; mt += 50 {
		t1 := t0.AddTau(MegaTau(mt).Tau())
		fmt.Printf("After %d mt: %v\n", mt, t1)
	}

	t1 := t0.AddTau(MegaTau(950).Tau())
	fmt.Printf("Time t1 is %v\n", t1)
	for mt := 1; mt <= 5; mt += 1 {
		t2 := t1.AddTau(MegaTau(mt).Tau())
		fmt.Printf("[%d] After %d mt: %v\n", 950+mt, mt, t2)
	}
	// Output: Time t0 is 1985-03-20 15:00:00 +0000 UTC
	// After 900 mt: 2013-09-26 07:00:00 +0000 UTC
	// After 950 mt: 2015-04-27 23:53:20 +0000 UTC
	// After 1000 mt: 2016-11-26 16:46:40 +0000 UTC
	// After 1050 mt: 2018-06-28 09:40:00 +0000 UTC
	// After 1100 mt: 2020-01-28 02:33:20 +0000 UTC
	// After 1150 mt: 2021-08-28 19:26:40 +0000 UTC
	// After 1200 mt: 2023-03-30 12:20:00 +0000 UTC
	// Time t1 is 2015-04-27 23:53:20 +0000 UTC
	// [951] After 1 mt: 2015-05-09 13:40:00 +0000 UTC
	// [952] After 2 mt: 2015-05-21 03:26:40 +0000 UTC
	// [953] After 3 mt: 2015-06-01 17:13:20 +0000 UTC
	// [954] After 4 mt: 2015-06-13 07:00:00 +0000 UTC
	// [955] After 5 mt: 2015-06-24 20:46:40 +0000 UTC
}
<|endoftext|>


<commit_before>// (C) 1990-2016.  Robert W Solomon.  All rights reserved.
// primes.go
package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
	//"strings"
	//
	//"hpcalc"
	"getcommandline"
	"makesubst"
	//                                                                                "holidaycalc"
	//                                                                                "timlibg"
	//                                                                                "tokenize"
	//                                                                                "timlibg"
)

const LastCompiled = "17 Feb 2018"

func main() {
	/*
	   This module tests my thoughts on prime factoring, derived from rpn.go
	   REVISION HISTORY
	   ----------------
	   24 Feb 17 -- Primes.go is derived from rpn.go
	   17 Feb 18 -- Made prime divisors a slice inested of an array.  Addressing syntax is the same.
	*/

	var INBUF string

	fmt.Println(" Prime Factoring Program.  Last compiled ", LastCompiled)
	fmt.Println()

	scanner := bufio.NewScanner(os.Stdin)
	if len(os.Args) > 1 {
		INBUF = getcommandline.GetCommandLineString()
		INBUF = makesubst.MakeSubst(INBUF)
	} else {
		fmt.Print(" Enter number to factor : ")
		scanner.Scan()
		INBUF = scanner.Text()
		if err := scanner.Err(); err != nil {
			fmt.Fprintln(os.Stderr, "reading standard input:", err)
			os.Exit(1)
		}
		if len(INBUF) == 0 {
			os.Exit(0)
		}
		INBUF = makesubst.MakeSubst(INBUF)
	} // if command tail exists

	N, err := strconv.Atoi(INBUF)
	if err != nil {
		fmt.Println(" Conversion to number failed.  Exiting")
		os.Exit(1)
	}

	PrimeFactors := PrimeFactorization(N)

	fmt.Print(" Prime factors for ", N, " are : ")
	for _, pf := range PrimeFactors {
		fmt.Print(pf, "  ")
	}

	fmt.Println()
} // end of main

// -------------------------------------------- PrimeFactorization ------------------------------

func PrimeFactorization(N int) []int {

	var PD = []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47} // Prime divisors array

	PrimeFactors := make([]int, 0, 10)

	n := N
	for i := 0; i < len(PD); i++ { // outer loop to sequentially test the prime divisors
		for n > 0 && n%PD[i] == 0 {
			PrimeFactors = append(PrimeFactors, PD[i])
			n = n / PD[i]
		}
		if n == 0 || IsPrimeInt(n) {
			PrimeFactors = append(PrimeFactors, n)
			break
		}
	}
	return PrimeFactors

} // PrimeFactorization

// ------------------------------------------------- IsPrimeInt64 -----------------
func IsPrimeInt64(n int) bool {

	var t uint64 = 3

	Uint := uint64(n)

	if Uint == 0 || Uint == 1 || Uint%2 == 0 {
		return false
	} else if Uint == 2 || Uint == 3 {
		return true
	}

	sqrt := math.Sqrt(float64(Uint))
	UintSqrt := uint64(sqrt)

	for t <= UintSqrt {
		if Uint%t == 0 {
			return false
		}
		t += 2
	}
	return true
} // IsPrimeInt64

// ------------------------------------------------- IsPrimeInt -----------------
func IsPrimeInt(n int) bool {

	var t uint = 3

	Uint := uint(n)

	if Uint == 0 || Uint == 1 || Uint%2 == 0 {
		return false
	} else if Uint == 2 || Uint == 3 {
		return true
	}

	sqrt := math.Sqrt(float64(Uint))
	UintSqrt := uint(sqrt)

	for t <= UintSqrt {
		if Uint%t == 0 {
			return false
		}
		t += 2
	}
	return true
} // IsPrime
<commit_msg>modified:   primes/primes.go -- broadened it.<commit_after>// (C) 1990-2016.  Robert W Solomon.  All rights reserved.
// primes.go
package main

import (
	"bufio"
	"fmt"
	"getcommandline"
	"makesubst"
	"math"
	"os"
	"strconv"
)

const LastCompiled = "25 Feb 2018"

func main() {
	/*
	   This module tests my thoughts on prime factoring, derived from rpn.go
	   REVISION HISTORY
	   ----------------
	   24 Feb 17 -- Primes.go is derived from rpn.go
	   17 Feb 18 -- Made prime divisors a slice instead of an array.  Addressing syntax is the same.
	   25 Feb 18 -- 736711 is trouble.  Will print out a factor.  And use uint.
	*/

	var INBUF string

	fmt.Println(" Prime Factoring Program.  Last compiled ", LastCompiled)
	fmt.Println()

	scanner := bufio.NewScanner(os.Stdin)
	if len(os.Args) > 1 {
		INBUF = getcommandline.GetCommandLineString()
		INBUF = makesubst.MakeSubst(INBUF)
	} else {
		fmt.Print(" Enter number to factor : ")
		scanner.Scan()
		INBUF = scanner.Text()
		if err := scanner.Err(); err != nil {
			fmt.Fprintln(os.Stderr, "reading standard input:", err)
			os.Exit(1)
		}
		if len(INBUF) == 0 {
			os.Exit(0)
		}
		INBUF = makesubst.MakeSubst(INBUF)
	} // if command tail exists

	//	N, err := strconv.Atoi(INBUF)
	U, err := strconv.ParseUint(INBUF, 10, 64)
	if err != nil {
		fmt.Println(" Conversion to number failed.  Exiting")
		os.Exit(1)
	}

	fac, primeflag := IsPrimeInt64(U)
	if primeflag {
		fmt.Println(U, " is prime.")
		os.Exit(0)
	} else {
		fmt.Print(U, " is NOT prime.")
		if fac != 0 {
			fmt.Println("  ", fac, " is its first factor")
		}
	}
	fmt.Println()

	N := int(U)
	PrimeFactors := PrimeFactorization(N)

	fmt.Print(" Prime factors for ", N, " are : ")
	for _, pf := range PrimeFactors {
		fmt.Print(pf, "  ")
	}

	fmt.Println()
} // end of main

// -------------------------------------------- PrimeFactorization ------------------------------

func PrimeFactorization(N int) []int {

	var PD = []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47} // Prime divisors array

	if N == 0 {
		return nil
	}

	PrimeFactors := make([]int, 0, 10)

	_, flag := IsPrimeInt(uint(N))
	if flag {
		PrimeFactors = append(PrimeFactors, N)
		return PrimeFactors
	}

	n := N
	for i := 0; i < len(PD); i++ { // outer loop to sequentially test the prime divisors
		for n > 0 && n%PD[i] == 0 {
			PrimeFactors = append(PrimeFactors, PD[i])
			n = n / PD[i]
		}
		_, primeflag := IsPrimeInt(uint(n))
		if primeflag {
			PrimeFactors = append(PrimeFactors, n)
			break
		}
	}
	return PrimeFactors

} // PrimeFactorization

// ------------------------------------------------- IsPrimeInt64 -----------------
func IsPrimeInt64(n uint64) (uint64, bool) {

	var t uint64 = 3

	//	Uint := uint64(n)
	Uint := n

	if Uint == 0 || Uint == 1 || Uint%2 == 0 {
		return 0, false
	} else if Uint == 2 || Uint == 3 {
		return Uint, true
	}

	sqrt := math.Sqrt(float64(Uint))
	UintSqrt := uint64(sqrt)

	for t <= UintSqrt {
		if Uint%t == 0 {
			return t, false
		}
		t += 2
	}
	return 0, true
} // IsPrimeInt64

// ------------------------------------------------- IsPrimeInt -----------------
func IsPrimeInt(n uint) (uint, bool) {

	var t uint = 3

	//	Uint := uint(n)
	Uint := n

	if Uint == 0 || Uint == 1 || Uint%2 == 0 {
		return 0, false
	} else if Uint == 2 || Uint == 3 {
		return Uint, true
	}

	sqrt := math.Sqrt(float64(Uint))
	UintSqrt := uint(sqrt)

	for t <= UintSqrt {
		if Uint%t == 0 {
			return t, false
		}
		t += 2
	}
	return 0, true
} // IsPrime
<|endoftext|>


<commit_before>// Copyright 2015 go-swagger maintainers
//
// 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 untader the License.

package validate

import (
	re "regexp"
	"sync"
)

// Cache for compiled regular expressions
var (
	cacheMutex = &sync.Mutex{}
	reDict     = map[string]*re.Regexp{}
)

func compileRegexp(pattern string) (*re.Regexp, error) {
	cacheMutex.Lock()
	defer cacheMutex.Unlock()
	// Save repeated regexp compilation
	if reDict[pattern] != nil {
		return reDict[pattern], nil
	}
	var err error
	reDict[pattern], err = re.Compile(pattern)
	return reDict[pattern], err
}

func mustCompileRegexp(pattern string) *re.Regexp {
	cacheMutex.Lock()
	defer cacheMutex.Unlock()
	// Save repeated regexp compilation, with panic on error
	if reDict[pattern] != nil {
		return reDict[pattern]
	}
	reDict[pattern] = re.MustCompile(pattern)
	return reDict[pattern]
}
<commit_msg>Avoid lock when regexp's cache is hot.<commit_after>// Copyright 2015 go-swagger maintainers
//
// 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 untader the License.

package validate

import (
	re "regexp"
	"sync"
	"sync/atomic"
)

// Cache for compiled regular expressions
var (
	cacheMutex = &sync.Mutex{}
	reDict     = atomic.Value{} //map[string]*re.Regexp
)

func compileRegexp(pattern string) (*re.Regexp, error) {
	cache, ok := reDict.Load().(map[string]*re.Regexp)
	if !ok {
		r, err := re.Compile(pattern)
		if err != nil {
			return nil, err
		}
		cacheRegexp(r)

		return r, nil
	}

	if r := cache[pattern]; r != nil {
		return r, nil
	}

	r, err := re.Compile(pattern)
	if err != nil {
		return nil, err
	}
	cacheRegexp(r)
	return r, nil
}

func mustCompileRegexp(pattern string) *re.Regexp {
	cache, ok := reDict.Load().(map[string]*re.Regexp)
	if !ok {
		r := re.MustCompile(pattern)
		cacheRegexp(r)
		return r
	}

	if r := cache[pattern]; r != nil {
		return r
	}

	r := re.MustCompile(pattern)
	cacheRegexp(r)
	return r
}

func cacheRegexp(r *re.Regexp) {
	cacheMutex.Lock()
	defer cacheMutex.Unlock()

	cache, ok := reDict.Load().(map[string]*re.Regexp)
	if !ok {
		cache = map[string]*re.Regexp{
			r.String(): r,
		}

		reDict.Store(cache)
		return
	}

	if cr := cache[r.String()]; cr == nil {
		newCache := map[string]*re.Regexp{
			r.String(): r,
		}

		for k, v := range cache {
			newCache[k] = v
		}

		reDict.Store(newCache)
	}

	return
}
<|endoftext|>


<commit_before>package torus

import (
	"math/big"

	"github.com/coreos/torus/models"
)

type RingType int

type Ring interface {
	GetPeers(key BlockRef) (PeerPermutation, error)
	Members() PeerList

	Describe() string
	Type() RingType
	Version() int

	Marshal() ([]byte, error)
}

type ModifyableRing interface {
	ChangeReplication(r int) (Ring, error)
}

type RingAdder interface {
	ModifyableRing
	AddPeers(PeerInfoList) (Ring, error)
}

type RingRemover interface {
	ModifyableRing
	RemovePeers(PeerList) (Ring, error)
}

type PeerPermutation struct {
	Replication int
	Peers       PeerList
}

type PeerList []string

func (pl PeerList) IndexAt(uuid string) int {
	for i, x := range pl {
		if x == uuid {
			return i
		}
	}
	return -1
}

func (pl PeerList) Has(uuid string) bool {
	return pl.IndexAt(uuid) != -1
}

func (pl PeerList) AndNot(b PeerList) PeerList {
	var out PeerList
	for _, x := range pl {
		if !b.Has(x) {
			out = append(out, x)
		}
	}
	return out
}

func (pl PeerList) Union(b PeerList) PeerList {
	var out PeerList
	for _, x := range pl {
		out = append(out, x)
	}
	for _, x := range b {
		if !pl.Has(x) {
			out = append(out, x)
		}
	}
	return out
}

func (pl PeerList) Intersect(b PeerList) PeerList {
	var out PeerList
	for _, x := range pl {
		if b.Has(x) {
			out = append(out, x)
		}
	}
	return out
}

// Applicative! Applicative! My kingdom for Applicative!

type PeerInfoList []*models.PeerInfo

func (pi PeerInfoList) UUIDAt(uuid string) int {
	for i, x := range pi {
		if x.UUID == uuid {
			return i
		}
	}
	return -1
}

func (pi PeerInfoList) HasUUID(uuid string) bool {
	return pi.UUIDAt(uuid) != -1
}

func (pi PeerInfoList) AndNot(b PeerList) PeerInfoList {
	var out PeerInfoList
	for _, x := range pi {
		if !b.Has(x.UUID) {
			out = append(out, x)
		}
	}
	return out
}

func (pi PeerInfoList) Union(b PeerInfoList) PeerInfoList {
	var out PeerInfoList
	for _, x := range pi {
		out = append(out, x)
	}
	for _, x := range b {
		if !pi.HasUUID(x.UUID) {
			out = append(out, x)
		}
	}
	return out
}

func (pi PeerInfoList) Intersect(b PeerInfoList) PeerInfoList {
	var out PeerInfoList
	for _, x := range pi {
		if b.HasUUID(x.UUID) {
			out = append(out, x)
		}
	}
	return out
}

func (pi PeerInfoList) PeerList() PeerList {
	out := make([]string, len(pi))
	for i, x := range pi {
		out[i] = x.UUID
	}
	return PeerList(out)
}

func (pi PeerInfoList) GetWeights() map[string]int {
	out := make(map[string]int)
	if len(pi) == 0 {
		return out
	}
	gcd := big.NewInt(int64(pi[0].TotalBlocks))
	for _, p := range pi[1:] {
		gcd.GCD(nil, nil, gcd, big.NewInt(int64(p.TotalBlocks)))
	}
	for _, p := range pi {
		out[p.UUID] = int(p.TotalBlocks / uint64(gcd.Int64()))
		clog.Infof("%s: %d", p.UUID, out[p.UUID])
	}
	return out
}
<commit_msg>ring: tiny: improve info message<commit_after>package torus

import (
	"math/big"

	"github.com/coreos/torus/models"
)

type RingType int

type Ring interface {
	GetPeers(key BlockRef) (PeerPermutation, error)
	Members() PeerList

	Describe() string
	Type() RingType
	Version() int

	Marshal() ([]byte, error)
}

type ModifyableRing interface {
	ChangeReplication(r int) (Ring, error)
}

type RingAdder interface {
	ModifyableRing
	AddPeers(PeerInfoList) (Ring, error)
}

type RingRemover interface {
	ModifyableRing
	RemovePeers(PeerList) (Ring, error)
}

type PeerPermutation struct {
	Replication int
	Peers       PeerList
}

type PeerList []string

func (pl PeerList) IndexAt(uuid string) int {
	for i, x := range pl {
		if x == uuid {
			return i
		}
	}
	return -1
}

func (pl PeerList) Has(uuid string) bool {
	return pl.IndexAt(uuid) != -1
}

func (pl PeerList) AndNot(b PeerList) PeerList {
	var out PeerList
	for _, x := range pl {
		if !b.Has(x) {
			out = append(out, x)
		}
	}
	return out
}

func (pl PeerList) Union(b PeerList) PeerList {
	var out PeerList
	for _, x := range pl {
		out = append(out, x)
	}
	for _, x := range b {
		if !pl.Has(x) {
			out = append(out, x)
		}
	}
	return out
}

func (pl PeerList) Intersect(b PeerList) PeerList {
	var out PeerList
	for _, x := range pl {
		if b.Has(x) {
			out = append(out, x)
		}
	}
	return out
}

// Applicative! Applicative! My kingdom for Applicative!

type PeerInfoList []*models.PeerInfo

func (pi PeerInfoList) UUIDAt(uuid string) int {
	for i, x := range pi {
		if x.UUID == uuid {
			return i
		}
	}
	return -1
}

func (pi PeerInfoList) HasUUID(uuid string) bool {
	return pi.UUIDAt(uuid) != -1
}

func (pi PeerInfoList) AndNot(b PeerList) PeerInfoList {
	var out PeerInfoList
	for _, x := range pi {
		if !b.Has(x.UUID) {
			out = append(out, x)
		}
	}
	return out
}

func (pi PeerInfoList) Union(b PeerInfoList) PeerInfoList {
	var out PeerInfoList
	for _, x := range pi {
		out = append(out, x)
	}
	for _, x := range b {
		if !pi.HasUUID(x.UUID) {
			out = append(out, x)
		}
	}
	return out
}

func (pi PeerInfoList) Intersect(b PeerInfoList) PeerInfoList {
	var out PeerInfoList
	for _, x := range pi {
		if b.HasUUID(x.UUID) {
			out = append(out, x)
		}
	}
	return out
}

func (pi PeerInfoList) PeerList() PeerList {
	out := make([]string, len(pi))
	for i, x := range pi {
		out[i] = x.UUID
	}
	return PeerList(out)
}

func (pi PeerInfoList) GetWeights() map[string]int {
	out := make(map[string]int)
	if len(pi) == 0 {
		return out
	}
	gcd := big.NewInt(int64(pi[0].TotalBlocks))
	for _, p := range pi[1:] {
		gcd.GCD(nil, nil, gcd, big.NewInt(int64(p.TotalBlocks)))
	}
	for _, p := range pi {
		out[p.UUID] = int(p.TotalBlocks / uint64(gcd.Int64()))
		clog.Infof("%s: weight %d", p.UUID, out[p.UUID])
	}
	return out
}
<|endoftext|>


<commit_before>package txtdirect

import (
	"fmt"
	"log"
	"net/http"
	"strconv"
	"strings"
)

// Fallback keeps the data necessary for the fallback flow
type Fallback struct {
	rw      http.ResponseWriter
	request *http.Request
	config  Config

	records    []Record
	pathRecord Record
	lastRecord Record

	fallbackType string
	code         int

	// Which record to use for fallback. (last record or path record)
	last        bool
	aggregation bool
}

// fallback redirects the request to the given fallback address
// and if it's not provided it will check txtdirect config for
// default fallback address
func fallback(w http.ResponseWriter, r *http.Request, fallbackType string, code int, c Config) {
	if code == http.StatusMovedPermanently {
		w.Header().Add("Cache-Control", fmt.Sprintf("max-age=%d", Status301CacheAge))
	}
	w.Header().Add("Status-Code", strconv.Itoa(code))

	f := Fallback{
		rw:           w,
		request:      r,
		config:       c,
		fallbackType: fallbackType,
		code:         code,
	}

	if fallbackType != "global" {
		// Fetch records from request's context and set the []record type on them
		f.fetchRecords()

		if !f.lastRecordFallback() {
			if !f.pathFallback() {
				// If non of the above cases applied on the record, jump into global redirects
				f.globalFallbacks(f.lastRecord.Type)
			}
		}
		log.Printf("[txtdirect]: %s > %s", r.Host+r.URL.Path, w.Header().Get("Location"))
		return
	}

	f.globalFallbacks("")

	log.Printf("[txtdirect]: %s > %s", r.Host+r.URL.Path, w.Header().Get("Location"))
}

func (f *Fallback) countFallback(recType string) {
	// if f.config.Prometheus.Enable {
	// 	FallbacksCount.WithLabelValues(f.request.Host, recType, f.fallbackType).Add(1)
	// 	RequestsByStatus.WithLabelValues(f.request.URL.Host, strconv.Itoa(f.code)).Add(1)
	// }
}

func (f *Fallback) globalFallbacks(recordType string) {
	if contains(f.config.Enable, "www") {
		s := strings.Join([]string{defaultProtocol, "://", defaultSub, ".", f.request.URL.Host}, "")

		http.Redirect(f.rw, f.request, s, f.code)

		f.countFallback(recordType)
	} else if f.config.Redirect != "" {
		f.rw.Header().Set("Status-Code", strconv.Itoa(http.StatusMovedPermanently))

		http.Redirect(f.rw, f.request, f.config.Redirect, http.StatusMovedPermanently)

		f.code = http.StatusMovedPermanently

		f.countFallback(recordType)
	} else {
		http.NotFound(f.rw, f.request)
	}
}

func (f *Fallback) fetchRecords() {
	f.records = f.request.Context().Value("records").([]Record)
	// Note: This condition should get changed when we support more record aggregations.
	if len(f.records) >= 2 {
		f.pathRecord = f.records[len(f.records)-2]
	}
	f.lastRecord = f.records[len(f.records)-1]
}

// Checks the last record's `to=`, `website=`, and `root=` field to fallback
// Returns false if it can't find an endpoint to fallback to
func (f *Fallback) lastRecordFallback() bool {
	// Redirect to first record's `to=` field
	if f.fallbackType == "to" && f.lastRecord.To != "" {
		http.Redirect(f.rw, f.request, f.lastRecord.To, f.code)
		f.countFallback(f.lastRecord.Type)
		return true
	}

	// Redirect to first record's `website=` field
	if f.fallbackType == "website" && f.lastRecord.Website != "" {
		http.Redirect(f.rw, f.request, f.lastRecord.Website, f.code)
		f.countFallback(f.lastRecord.Type)
		return true
	}

	// Redirect to first record's `root=` field
	if f.fallbackType == "root" && f.lastRecord.Root != "" {
		http.Redirect(f.rw, f.request, f.lastRecord.Root, f.code)
		f.countFallback(f.lastRecord.Type)
		return true
	}
	return false
}

// Checks the path record's `to=`, `website=`, and `root=` field to fallback
// Returns false if it can't find an endpoint to fallback to
func (f *Fallback) pathFallback() bool {
	// Redirect to path record's `website=` field
	if f.fallbackType == "website" && f.pathRecord.Website != "" {
		http.Redirect(f.rw, f.request, f.pathRecord.Website, f.code)
		f.countFallback(f.pathRecord.Type)
		return true
	}

	// Redirect to path record's `root=` field
	if f.fallbackType == "root" && f.pathRecord.Root != "" {
		http.Redirect(f.rw, f.request, f.pathRecord.Root, f.code)
		f.countFallback(f.pathRecord.Type)
		return true
	}

	// Redirect to path record's `to=` field
	if f.pathRecord.To != "" {
		http.Redirect(f.rw, f.request, f.pathRecord.To, f.code)
		f.countFallback(f.pathRecord.Type)
		return true
	}
	return false
}
<commit_msg>(v2): Remove commented prometheus codes<commit_after>package txtdirect

import (
	"fmt"
	"log"
	"net/http"
	"strconv"
	"strings"
)

// Fallback keeps the data necessary for the fallback flow
type Fallback struct {
	rw      http.ResponseWriter
	request *http.Request
	config  Config

	records    []Record
	pathRecord Record
	lastRecord Record

	fallbackType string
	code         int

	// Which record to use for fallback. (last record or path record)
	last        bool
	aggregation bool
}

// fallback redirects the request to the given fallback address
// and if it's not provided it will check txtdirect config for
// default fallback address
func fallback(w http.ResponseWriter, r *http.Request, fallbackType string, code int, c Config) {
	if code == http.StatusMovedPermanently {
		w.Header().Add("Cache-Control", fmt.Sprintf("max-age=%d", Status301CacheAge))
	}
	w.Header().Add("Status-Code", strconv.Itoa(code))

	f := Fallback{
		rw:           w,
		request:      r,
		config:       c,
		fallbackType: fallbackType,
		code:         code,
	}

	if fallbackType != "global" {
		// Fetch records from request's context and set the []record type on them
		f.fetchRecords()

		if !f.lastRecordFallback() {
			if !f.pathFallback() {
				// If non of the above cases applied on the record, jump into global redirects
				f.globalFallbacks(f.lastRecord.Type)
			}
		}
		log.Printf("[txtdirect]: %s > %s", r.Host+r.URL.Path, w.Header().Get("Location"))
		return
	}

	f.globalFallbacks("")

	log.Printf("[txtdirect]: %s > %s", r.Host+r.URL.Path, w.Header().Get("Location"))
}

func (f *Fallback) globalFallbacks(recordType string) {
	if contains(f.config.Enable, "www") {
		s := strings.Join([]string{defaultProtocol, "://", defaultSub, ".", f.request.URL.Host}, "")

		http.Redirect(f.rw, f.request, s, f.code)

	} else if f.config.Redirect != "" {
		f.rw.Header().Set("Status-Code", strconv.Itoa(http.StatusMovedPermanently))

		http.Redirect(f.rw, f.request, f.config.Redirect, http.StatusMovedPermanently)

		f.code = http.StatusMovedPermanently

	} else {
		http.NotFound(f.rw, f.request)
	}
}

func (f *Fallback) fetchRecords() {
	f.records = f.request.Context().Value("records").([]Record)
	// Note: This condition should get changed when we support more record aggregations.
	if len(f.records) >= 2 {
		f.pathRecord = f.records[len(f.records)-2]
	}
	f.lastRecord = f.records[len(f.records)-1]
}

// Checks the last record's `to=`, `website=`, and `root=` field to fallback
// Returns false if it can't find an endpoint to fallback to
func (f *Fallback) lastRecordFallback() bool {
	// Redirect to first record's `to=` field
	if f.fallbackType == "to" && f.lastRecord.To != "" {
		http.Redirect(f.rw, f.request, f.lastRecord.To, f.code)
		return true
	}

	// Redirect to first record's `website=` field
	if f.fallbackType == "website" && f.lastRecord.Website != "" {
		http.Redirect(f.rw, f.request, f.lastRecord.Website, f.code)
		return true
	}

	// Redirect to first record's `root=` field
	if f.fallbackType == "root" && f.lastRecord.Root != "" {
		http.Redirect(f.rw, f.request, f.lastRecord.Root, f.code)
		return true
	}
	return false
}

// Checks the path record's `to=`, `website=`, and `root=` field to fallback
// Returns false if it can't find an endpoint to fallback to
func (f *Fallback) pathFallback() bool {
	// Redirect to path record's `website=` field
	if f.fallbackType == "website" && f.pathRecord.Website != "" {
		http.Redirect(f.rw, f.request, f.pathRecord.Website, f.code)
		return true
	}

	// Redirect to path record's `root=` field
	if f.fallbackType == "root" && f.pathRecord.Root != "" {
		http.Redirect(f.rw, f.request, f.pathRecord.Root, f.code)
		return true
	}

	// Redirect to path record's `to=` field
	if f.pathRecord.To != "" {
		http.Redirect(f.rw, f.request, f.pathRecord.To, f.code)
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package procfs

import (
	"io/ioutil"
	"os"
	"path"
	"strconv"
)

const procfsdir = "/proc"

type Filler interface {
	Fill()
}

type Lister interface {
	List(string)
}

type Getter interface {
	Get(string)
}

type ProcFS struct {
	Processes map[string]*Process
	Self      string
}

const (
	PROCFS_PROCESSES = "Processes"
	PROCFS_SELF = "Self"
)

func (pfs *ProcFS) Fill() {
	pfs.List(PROCFS_PROCESSES)
	pfs.Get(PROCFS_SELF)
}

func (pfs *ProcFS) List(k string) {
	switch k {
	case PROCFS_PROCESSES:
		if !exists(procfsdir) {
			return
		}
		pfs.Processes = make(map[string]*Process)
		ds, err := ioutil.ReadDir(procfsdir)
		if err != nil {
			return
		}
		// get all numeric entries
		for _, d := range ds {
			n := d.Name
			id, err := strconv.Atoi(n)
			if isNumeric(n) && err != nil {
				proc := Process{PID: id}
				pfs.Processes[n] = &proc
			}
		}
	}
}

func (pfs *ProcFS) Get(k string) {
	switch k {
	case PROCFS_SELF:
		var selfdir = path.Join(procfsdir, "self")
		if !exists(selfdir) {
			return
		}
		fi, _ := os.Readlink(selfdir)
		pfs.Self = fi
	}
}

type Process struct {
	PID     int
	Auxv    []byte
	Cmdline []string
	Cwd     string
	Environ map[string]string
	Exe     string
	Fds     map[int]*Fd
	Root    string
	Status  map[string]string
	Threads map[int]*Thread
}
// TODO limits, maps, mem, mountinfo, mounts, mountstats, ns, smaps, stat

const (
	PROCFS_PROC_AUXV = "Process.Auxv"
	PROCFS_PROC_CMDLINE = "Process.Cmdline"
	PROCFS_PROC_CWD = "Process.Cwd"
	PROCFS_PROC_ENVIRON = "Process.Environ"
	PROCFS_PROC_EXE = "Process.Exe"
	PROCFS_PROC_ROOT = "Process.Root"
	PROCFS_PROC_STATUS = "Process.Status"

	PROCFS_PROC_FDS = "Process.Fds"
	PROCFS_PROC_THREADS = "Process.Threads"
)

func (p *Process) Fill() {
	p.Get(PROCFS_PROC_AUXV)
	p.Get(PROCFS_PROC_CMDLINE)
	p.Get(PROCFS_PROC_CWD)
	p.Get(PROCFS_PROC_ENVIRON)
	p.Get(PROCFS_PROC_EXE)
	p.Get(PROCFS_PROC_ROOT)
	p.Get(PROCFS_PROC_STATUS)

	// Fds
	p.List(PROCFS_PROC_FDS)
	for _, f := range p.Fds {
		f.Fill()
	}

	// Threads
	p.List(PROCFS_PROC_THREADS)
	for _, t := range p.Threads {
		t.Fill()
	}
}

func (p *Process) List(k string) {

}

func (p *Process) Get(k string) {
	pdir := path.Join(procfsdir, strconv.Itoa(p.PID))
	switch k {
	case PROCFS_PROC_AUXV:
		p.Auxv, _ = ioutil.ReadFile(path.Join(pdir, "auxv"))
	case PROCFS_PROC_CMDLINE:
		cl, err := ioutil.ReadFile(path.Join(pdir, "cmdline"))
		if err == nil {
			p.Cmdline = splitNull(cl)
		}
	case PROCFS_PROC_CWD:
		p.Cwd, _ = os.Readlink(path.Join(pdir, "cwd"))
	case PROCFS_PROC_ENVIRON:
	}
}

type Fd struct {
	Path  string
	Pos   int
	Flags int
}

const (
	PROCFS_PROC_FD_PATH = "Process.Fd.Path"
	PROCFS_PROC_FD_POS = "Process.Fd.Pos"
	PROCFS_PROC_FD_FLAGS = "Process.Fd.Flags"
)

func (f *Fd) Fill() {
	f.Get(PROCFS_PROC_FD_PATH)
	f.Get(PROCFS_PROC_FD_POS)
	f.Get(PROCFS_PROC_FD_FLAGS)
}

func (f *Fd) Get(k string) {
	switch k {

	}
}

type Thread struct {
	// TODO
}

func (t *Thread) Fill() {

}

func (t *Thread) Get(k string) {

}
<commit_msg>And changing all other types<commit_after>package procfs

import (
	"io/ioutil"
	"os"
	"path"
	"strconv"
)

const procfsdir = "/proc"

type Filler interface {
	Fill()
}

type Lister interface {
	List(string)
}

type Getter interface {
	Get(string)
}

type ProcFS struct {
	Processes map[string]*Process
	Self      string
}

const (
	PROCFS_PROCESSES = "Processes"
	PROCFS_SELF = "Self"
)

func (pfs *ProcFS) Fill() {
	pfs.List(PROCFS_PROCESSES)
	pfs.Get(PROCFS_SELF)
}

func (pfs *ProcFS) List(k string) {
	switch k {
	case PROCFS_PROCESSES:
		if !exists(procfsdir) {
			return
		}
		pfs.Processes = make(map[string]*Process)
		ds, err := ioutil.ReadDir(procfsdir)
		if err != nil {
			return
		}
		// get all numeric entries
		for _, d := range ds {
			n := d.Name
			id, err := strconv.Atoi(n)
			if isNumeric(n) && err != nil {
				proc := Process{PID: id}
				pfs.Processes[n] = &proc
			}
		}
	}
}

func (pfs *ProcFS) Get(k string) {
	switch k {
	case PROCFS_SELF:
		var selfdir = path.Join(procfsdir, "self")
		if !exists(selfdir) {
			return
		}
		fi, _ := os.Readlink(selfdir)
		pfs.Self = fi
	}
}

type Process struct {
	PID     int
	Auxv    []byte
	Cmdline []string
	Cwd     string
	Environ map[string]string
	Exe     string
	Fds     map[string]*Fd
	Root    string
	Status  map[string]string
	Threads map[string]*Thread
}
// TODO limits, maps, mem, mountinfo, mounts, mountstats, ns, smaps, stat

const (
	PROCFS_PROC_AUXV = "Process.Auxv"
	PROCFS_PROC_CMDLINE = "Process.Cmdline"
	PROCFS_PROC_CWD = "Process.Cwd"
	PROCFS_PROC_ENVIRON = "Process.Environ"
	PROCFS_PROC_EXE = "Process.Exe"
	PROCFS_PROC_ROOT = "Process.Root"
	PROCFS_PROC_STATUS = "Process.Status"

	PROCFS_PROC_FDS = "Process.Fds"
	PROCFS_PROC_THREADS = "Process.Threads"
)

func (p *Process) Fill() {
	p.Get(PROCFS_PROC_AUXV)
	p.Get(PROCFS_PROC_CMDLINE)
	p.Get(PROCFS_PROC_CWD)
	p.Get(PROCFS_PROC_ENVIRON)
	p.Get(PROCFS_PROC_EXE)
	p.Get(PROCFS_PROC_ROOT)
	p.Get(PROCFS_PROC_STATUS)

	// Fds
	p.List(PROCFS_PROC_FDS)
	for _, f := range p.Fds {
		f.Fill()
	}

	// Threads
	p.List(PROCFS_PROC_THREADS)
	for _, t := range p.Threads {
		t.Fill()
	}
}

func (p *Process) List(k string) {

}

func (p *Process) Get(k string) {
	pdir := path.Join(procfsdir, strconv.Itoa(p.PID))
	switch k {
	case PROCFS_PROC_AUXV:
		p.Auxv, _ = ioutil.ReadFile(path.Join(pdir, "auxv"))
	case PROCFS_PROC_CMDLINE:
		cl, err := ioutil.ReadFile(path.Join(pdir, "cmdline"))
		if err == nil {
			p.Cmdline = splitNull(cl)
		}
	case PROCFS_PROC_CWD:
		p.Cwd, _ = os.Readlink(path.Join(pdir, "cwd"))
	case PROCFS_PROC_ENVIRON:
	}
}

type Fd struct {
	Path  string
	Pos   int
	Flags int
}

const (
	PROCFS_PROC_FD_PATH = "Process.Fd.Path"
	PROCFS_PROC_FD_POS = "Process.Fd.Pos"
	PROCFS_PROC_FD_FLAGS = "Process.Fd.Flags"
)

func (f *Fd) Fill() {
	f.Get(PROCFS_PROC_FD_PATH)
	f.Get(PROCFS_PROC_FD_POS)
	f.Get(PROCFS_PROC_FD_FLAGS)
}

func (f *Fd) Get(k string) {
	switch k {

	}
}

type Thread struct {
	// TODO
}

func (t *Thread) Fill() {

}

func (t *Thread) Get(k string) {

}
<|endoftext|>


<commit_before>// Package fallback provides an enhanced degree of redundancy to HTTP requests
// by introducing a chain of responsibility, consisting of a series of fallback
// HTTP requests, to augment an initial HTTP request. Should the initial HTTP
// request fail, the next fallback HTTP request in the chain will execute. Any
// number of fallback HTTP requests can be chained sequentially. Redundancy is
// achieved by executing each fallback HTTP request in a recursive manner until
// one of the requests succeeds, or all requests fail.
package fallback

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
)

type Connecter interface {
	GetName() string

	CreateHTTPRequest(method, path string, body []byte,
		headers map[string]string) (*http.Request, error)

	ExecuteHTTPRequest(method, path string, body []byte,
		headers map[string]string) (int, error)
}

type Connection struct {
	name        string
	host        string
	output      interface{}
	customError interface{}
	fallback    Connecter
}

func NewConnection(name, host string, output interface{},
	customError interface{}, fallback Connecter) *Connection {

	return &Connection{name, host, output, customError, fallback}
}

func (connection Connection) GetName() string {

	return connection.name
}

func (connection Connection) CreateHTTPRequest(method, path string,
	body []byte, headers map[string]string) (*http.Request, error) {

	var request *http.Request
	var err error

	if body == nil {
		request, err = http.NewRequest(method, connection.host+"/"+path, nil)
	} else {
		request, err = http.NewRequest(method, connection.host+"/"+path, bytes.NewBuffer(body))
	}

	if err != nil {
		return nil, err
	}

	for key := range headers {
		request.Header.Add(key, headers[key])
	}
	return request, nil
}

func (connection Connection) ExecuteHTTPRequest(method, path string,
	body []byte, headers map[string]string) (int, error) {

	client := &http.Client{}

	request, err := connection.CreateHTTPRequest(method, path, body, headers)
	if err != nil {
		if connection.fallback != nil {
			statusCode, err :=
				connection.fallback.ExecuteHTTPRequest(method, path, body, headers)
			if statusCode < 200 || statusCode > 299 {
				return statusCode, err
			}
			return statusCode, nil
		}
		return 400, err // This error will occur if the URI is malformed or otherwise invalid.
	}

	resp, err := client.Do(request)
	if err != nil {
		if connection.fallback != nil {
			statusCode, err :=
				connection.fallback.ExecuteHTTPRequest(method, path, body, headers)
			if statusCode < 200 || statusCode > 299 {
				return statusCode, err
			}
			return statusCode, nil
		}
		return 503, err // This error will occur if the URI is unreachable.
	}
	defer resp.Body.Close()

	if resp.StatusCode == 404 {
		if connection.fallback != nil {
			statusCode, err :=
				connection.fallback.ExecuteHTTPRequest(method, path, body, headers)
			if statusCode < 200 || statusCode > 299 {
				return statusCode, err
			}
			return statusCode, nil
		}
		return 404, nil
	} else if resp.StatusCode < 200 || resp.StatusCode > 299 {
		if connection.fallback != nil {
			statusCode, err :=
				connection.fallback.ExecuteHTTPRequest(method, path, body, headers)
			if statusCode < 200 || statusCode > 299 {
				return statusCode, err
			}
			return statusCode, nil
		}

		dec := json.NewDecoder(resp.Body)

		err := dec.Decode(connection.customError)
		if err != nil {
			return resp.StatusCode, errors.New("Unable to parse custom error.")
		}
		return resp.StatusCode, nil
	} else {
		dec := json.NewDecoder(resp.Body)

		err := dec.Decode(connection.output)
		if err != nil {
			return resp.StatusCode, errors.New("Unable to parse custom error.")
		}
		return resp.StatusCode, nil
	}
}
<commit_msg>Added struct-level documentation<commit_after>// Package fallback provides an enhanced degree of redundancy to HTTP requests
// by introducing a Chain of Responsibility, consisting of a series of fallback
// HTTP requests, to augment an initial HTTP request. Should the initial HTTP
// request fail, the next fallback HTTP request in the chain will execute. Any
// number of fallback HTTP requests can be chained sequentially. Redundancy is
// achieved by executing each fallback HTTP request in a recursive manner until
// one of the requests succeeds, or all requests fail.
package fallback

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
)

// Connecter represents the Handler abstraction in the Chain of Responsibility
// that consists of a series of fallback HTTP requests. It provides a contract
// which defines the prerequisites that implementations must adhere to in order
// to take part in the chain.
type Connecter interface {
	GetName() string

	CreateHTTPRequest(method, path string, body []byte,
		headers map[string]string) (*http.Request, error)

	ExecuteHTTPRequest(method, path string, body []byte,
		headers map[string]string) (int, error)
}

// Connection represents a Concrete Handler implementation in the Chain of
// Responsibility that consists of a series of fallback HTTP requests.
// Consuming clients can utilise this class directly, as per the examples
// provided, or provide custom implementations derived from Connecter.
type Connection struct {
	// The name used to describe the Connection.
	Name string
	// The Host URI segment excluding other segments such as query string.
	Host string
	// A custom struct that represents a deserialised object returned as result
	// of a successful HTTP request.
	Output      interface{}
	CustomError interface{}
	Fallback    Connecter
}

// NewConnection returns a new Connection instance based on the supplied
// metadata pertaining to Connection.
func NewConnection(name, host string, output interface{},
	customError interface{}, fallback Connecter) *Connection {

	return &Connection{name, host, output, customError, fallback}
}

// GetName returns the Connection name.
func (connection Connection) GetName() string {

	return connection.Name
}

func (connection Connection) CreateHTTPRequest(method, path string,
	body []byte, headers map[string]string) (*http.Request, error) {

	var request *http.Request
	var err error

	if body == nil {
		request, err = http.NewRequest(method, connection.Host+"/"+path, nil)
	} else {
		request, err = http.NewRequest(method, connection.Host+"/"+path, bytes.NewBuffer(body))
	}

	if err != nil {
		return nil, err
	}

	for key := range headers {
		request.Header.Add(key, headers[key])
	}
	return request, nil
}

func (connection Connection) ExecuteHTTPRequest(method, path string,
	body []byte, headers map[string]string) (int, error) {

	client := &http.Client{}

	request, err := connection.CreateHTTPRequest(method, path, body, headers)
	if err != nil {
		if connection.Fallback != nil {
			statusCode, err :=
				connection.Fallback.ExecuteHTTPRequest(method, path, body, headers)
			if statusCode < 200 || statusCode > 299 {
				return statusCode, err
			}
			return statusCode, nil
		}
		return 400, err // This error will occur if the URI is malformed or otherwise invalid.
	}

	resp, err := client.Do(request)
	if err != nil {
		if connection.Fallback != nil {
			statusCode, err :=
				connection.Fallback.ExecuteHTTPRequest(method, path, body, headers)
			if statusCode < 200 || statusCode > 299 {
				return statusCode, err
			}
			return statusCode, nil
		}
		return 503, err // This error will occur if the URI is unreachable.
	}
	defer resp.Body.Close()

	if resp.StatusCode == 404 {
		if connection.Fallback != nil {
			statusCode, err :=
				connection.Fallback.ExecuteHTTPRequest(method, path, body, headers)
			if statusCode < 200 || statusCode > 299 {
				return statusCode, err
			}
			return statusCode, nil
		}
		return 404, nil
	} else if resp.StatusCode < 200 || resp.StatusCode > 299 {
		if connection.Fallback != nil {
			statusCode, err :=
				connection.Fallback.ExecuteHTTPRequest(method, path, body, headers)
			if statusCode < 200 || statusCode > 299 {
				return statusCode, err
			}
			return statusCode, nil
		}

		dec := json.NewDecoder(resp.Body)

		err := dec.Decode(connection.CustomError)
		if err != nil {
			return resp.StatusCode, errors.New("Unable to parse custom error.")
		}
		return resp.StatusCode, nil
	} else {
		dec := json.NewDecoder(resp.Body)

		err := dec.Decode(connection.Output)
		if err != nil {
			return resp.StatusCode, errors.New("Unable to parse custom error.")
		}
		return resp.StatusCode, nil
	}
}
<|endoftext|>


<commit_before>// problem51.go
//
// By replacing the 1st digit of the 2-digit number *3, it turns out that six of
// the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime.
//
// By replacing the 3rd and 4th digits of 56**3 with the same digit, this 5-digit
// number is the first example having seven primes among the ten generated
// numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and
// 56993. Consequently 56003, being the first member of this family, is the
// smallest prime with this property.
//
// Find the smallest prime which, by replacing part of the number (not necessarily
// adjacent digits) with the same digit, is part of an eight prime value family.

package main

import (
	"euler/tools"
	"fmt"
	"math"
)

// toDigits converts an int to a []int representing its digits.
// e.g. 1234 -> [1 2 3 4]
func toDigits(n int) []int {
	var ds []int
	for n != 0 {
		ds = append(ds, n%10)
		n = int(n / 10)
	}
	tools.ReverseInts(ds)
	return ds
}

// toNum converts a []int representing digits to an int
// e.g. [1 2 3 4] -> 1234
func toNum(digits []int) int {
	var n int
	for i, x := range tools.ReversedInts(digits) {
		n += x * int(math.Pow(10, float64(i)))
	}
	return n
}

// Our strategy is as follows. Since we are seeking an eight prime family, it
// must be the case that the pattern of digits which are replaced contains
// either 0, 1, or 2 in the smallest family member. Therefore, we can search
// through primes and replace digits in patterns specified by the locations 0,
// 1, and 2. If the family of numbers that results contains eight primes, we
// have found the solution.

// In the example given, 56003 is the smallest member of an eight prime family.
// We would find the pattern of 0s at indices (2, 3) to produce the
// corresponding family from 56**3.

// findIndices returns three slices, where each contains the indices in the
// given number of the digits 0, 1, and 2 respectively.
// e.g. 18209912 -> [[3], [0 6], [2 7]]
// e.g. 56003 -> [[2 3], [], []]
func findIndices(n int) [][]int {
	var indices [][]int
	for _, target := range []int{0, 1, 2} {
		var found []int
		for i, x := range toDigits(n) {
			if x == target {
				found = append(found, i)
			}
		}
		indices = append(indices, found)
	}
	return indices
}

// family returns the family of numbers resulting from replacing
// digits at the specific indices with the digits 0 to 9.
// e.g. 56003, [2 3] -> [56003, 56113, 56223, 56333, 56443, ...]
func family(n int, indices []int) []int {
	var fam []int
	digits := toDigits(n)
	for i := 0; i < 10; i++ {
		for _, idx := range indices {
			digits[idx] = i
		}
		// return sentinel value (-1) in case of leading zero
		if digits[0] == 0 {
			fam = append(fam, -1)
		} else {
			fam = append(fam, toNum(digits))
		}
	}
	return fam
}

// isSmallestMember checks whether the given number satisfies
// the problem description.
func isSmallestMember(n int) bool {
	for _, indices := range findIndices(n) {
		var primes []int
		for _, x := range family(n, indices) {
			if tools.IsPrime(x) {
				primes = append(primes, x)
			}
		}
		if len(primes) == 8 {
			return true
		}
	}
	return false
}

func problem51() int {
	for p := range tools.GetPrimesFrom(56995) {
		if isSmallestMember(p) {
			return p
		}
	}
	return -1
}

func main() {
	ans := problem51()
	fmt.Println(ans)
}
<commit_msg>Add comment highlighting infinite stream<commit_after>// problem51.go
//
// By replacing the 1st digit of the 2-digit number *3, it turns out that six of
// the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime.
//
// By replacing the 3rd and 4th digits of 56**3 with the same digit, this 5-digit
// number is the first example having seven primes among the ten generated
// numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and
// 56993. Consequently 56003, being the first member of this family, is the
// smallest prime with this property.
//
// Find the smallest prime which, by replacing part of the number (not necessarily
// adjacent digits) with the same digit, is part of an eight prime value family.

package main

import (
	"euler/tools"
	"fmt"
	"math"
)

// toDigits converts an int to a []int representing its digits.
// e.g. 1234 -> [1 2 3 4]
func toDigits(n int) []int {
	var ds []int
	for n != 0 {
		ds = append(ds, n%10)
		n = int(n / 10)
	}
	tools.ReverseInts(ds)
	return ds
}

// toNum converts a []int representing digits to an int
// e.g. [1 2 3 4] -> 1234
func toNum(digits []int) int {
	var n int
	for i, x := range tools.ReversedInts(digits) {
		n += x * int(math.Pow(10, float64(i)))
	}
	return n
}

// Our strategy is as follows. Since we are seeking an eight prime family, it
// must be the case that the pattern of digits which are replaced contains
// either 0, 1, or 2 in the smallest family member. Therefore, we can search
// through primes and replace digits in patterns specified by the locations 0,
// 1, and 2. If the family of numbers that results contains eight primes, we
// have found the solution.

// In the example given, 56003 is the smallest member of an eight prime family.
// We would find the pattern of 0s at indices (2, 3) to produce the
// corresponding family from 56**3.

// findIndices returns three slices, where each contains the indices in the
// given number of the digits 0, 1, and 2 respectively.
// e.g. 18209912 -> [[3], [0 6], [2 7]]
// e.g. 56003 -> [[2 3], [], []]
func findIndices(n int) [][]int {
	var indices [][]int
	for _, target := range []int{0, 1, 2} {
		var found []int
		for i, x := range toDigits(n) {
			if x == target {
				found = append(found, i)
			}
		}
		indices = append(indices, found)
	}
	return indices
}

// family returns the family of numbers resulting from replacing
// digits at the specific indices with the digits 0 to 9.
// e.g. 56003, [2 3] -> [56003, 56113, 56223, 56333, 56443, ...]
func family(n int, indices []int) []int {
	var fam []int
	digits := toDigits(n)
	for i := 0; i < 10; i++ {
		for _, idx := range indices {
			digits[idx] = i
		}
		// return sentinel value (-1) in case of leading zero
		if digits[0] == 0 {
			fam = append(fam, -1)
		} else {
			fam = append(fam, toNum(digits))
		}
	}
	return fam
}

// isSmallestMember checks whether the given number satisfies
// the problem description.
func isSmallestMember(n int) bool {
	for _, indices := range findIndices(n) {
		var primes []int
		for _, x := range family(n, indices) {
			if tools.IsPrime(x) {
				primes = append(primes, x)
			}
		}
		if len(primes) == 8 {
			return true
		}
	}
	return false
}

func problem51() int {
	for p := range tools.GetPrimesFrom(56995) { // infinite stream
		if isSmallestMember(p) {
			return p
		}
	}
	return -1
}

func main() {
	ans := problem51()
	fmt.Println(ans)
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Datacratic. All rights reserved.

package rest_test

import (
	"github.com/datacratic/gorest/rest"

	"errors"
	"fmt"
	"net"
	"net/http"
	"time"
)

// Our service that we want to expose through a REST api.
type PingService struct{}

func (*PingService) Ping(tick int) int { return tick }
func (*PingService) PingError() error  { return errors.New("BOOM") }
func (*PingService) PingDelay() int    { time.Sleep(5 * time.Second); return 1 }

// RESTRoutes implements the rest.Routable interface which is used by
// rest.Endpoint to route incoming HTTP request to the appropriate handler.
func (svc *PingService) RESTRoutes() rest.Routes {

	return rest.Routes{

		// Route with no arguments provided in the path means that the argument
		// required by Ping will be taken from the body of the HTTP request. The
		// body is assumed to be JSON and will automatically be unmarshalled.
		//
		// The function's return value will be automatically serialized to JSON
		// using the encoding.json package and used as the body of the HTTP
		// response sent to the client. If nothing or nil is returned then an
		// HTTP 204 response code is returned instead.
		rest.NewRoute("/ping", "POST", svc.Ping),

		// Path components starting with ':' indicates that the first argument
		// of the Ping function will be fed from the value found where the
		// placeholder is in the path.
		//
		// Path arguments are assumed to be basic types (string, bool, int
		// floats) and are automatically converted to match the function
		// argument.
		rest.NewRoute("/ping/:tick", "PUT", svc.Ping),

		// We can also return errors which will automatically be detected and
		// converted to a HTTP 400 return code to the user. The HTTP return code
		// can be changed by returning a rest.CodedError.
		//
		// The body is returned as a simple string containing the string
		// representation of the error object.
		rest.NewRoute("/ping/error", "POST", svc.PingError),

		// Used for testing the Timeout() feature of a request.
		rest.NewRoute("/ping/delay", "GET", svc.PingDelay),
	}
}

func ExamplePing() {

	// Add our service that implements the rest.Routable interface to our
	// endpoint. We can also add simple lambda functions to our endpoint.
	rest.AddService(new(PingService))
	rest.AddRoute("/simple", "POST", func(tick int) int { return tick })

	// The endpoint is started like any other http.Server.
	go rest.ListenAndServe(":12345", nil)

	// The rest package also provides a way to query a REST endpoint by
	// incrementally building a REST request. The body of the query can be set
	// via the SetBody() function which will serialize the object to JSON using
	// the encoding.json package.
	simpleResp := rest.NewRequest("http://localhost:12345", "POST").
		SetPath("/simple").
		SetBody(123).
		Send()

	// The rest.Response object contains the result of the REST request and can
	// be used to deserialize the JSON body into the provided object using the
	// encoding.json package.
	var tick int
	if err := simpleResp.GetBody(&tick); err != nil {
		panic("Whoops!")
	}
	fmt.Println("ping-simple:", tick)

	// The REST client can also be customized by manually creating a rest.Client
	// which can then be used to create REST requests. rest.Client embdeds an
	// http.Client struct which can be used to customize the HTTP requests.
	client := &rest.Client{Host: "http://localhost:12345", Root: "/ping"}
	clientResp := client.NewRequest("PUT").
		SetPath("%d", 321).
		AddParam("test", "321").
		AddParam("test2", "3212").
		Send()

	if err := clientResp.GetBody(&tick); err != nil {
		panic("Whoops!")
	}
	fmt.Println("ping-client:", tick)

	// The REST client can check if a response timed out.
	dialer := net.Dialer{Timeout: 500 * time.Millisecond}
	clientTime := &rest.Client{
		Host: "http://localhost:12345",
		Root: "/ping",
		Client: &http.Client{
			Transport: &http.Transport{Dial: dialer.Dial},
			Timeout:   500 * time.Millisecond,
		},
	}
	timeoutResp := clientTime.NewRequest("GET").
		SetPath("delay").
		Send()

	if err := timeoutResp.GetBody(&tick); err == nil {
		panic("Whoops! Should time out" + fmt.Sprint(tick))
	}

	// Output:
	// ping-simple: 123
	// ping-client: 321
}
<commit_msg>added a sleep to let some time for the server to launch, added example timeout check<commit_after>// Copyright (c) 2014 Datacratic. All rights reserved.

package rest_test

import (
	"github.com/datacratic/gorest/rest"

	"errors"
	"fmt"
	"net"
	"net/http"
	"time"
)

// Our service that we want to expose through a REST api.
type PingService struct{}

func (*PingService) Ping(tick int) int { return tick }
func (*PingService) PingError() error  { return errors.New("BOOM") }
func (*PingService) PingDelay() int    { time.Sleep(5 * time.Second); return 1 }

// RESTRoutes implements the rest.Routable interface which is used by
// rest.Endpoint to route incoming HTTP request to the appropriate handler.
func (svc *PingService) RESTRoutes() rest.Routes {

	return rest.Routes{

		// Route with no arguments provided in the path means that the argument
		// required by Ping will be taken from the body of the HTTP request. The
		// body is assumed to be JSON and will automatically be unmarshalled.
		//
		// The function's return value will be automatically serialized to JSON
		// using the encoding.json package and used as the body of the HTTP
		// response sent to the client. If nothing or nil is returned then an
		// HTTP 204 response code is returned instead.
		rest.NewRoute("/ping", "POST", svc.Ping),

		// Path components starting with ':' indicates that the first argument
		// of the Ping function will be fed from the value found where the
		// placeholder is in the path.
		//
		// Path arguments are assumed to be basic types (string, bool, int
		// floats) and are automatically converted to match the function
		// argument.
		rest.NewRoute("/ping/:tick", "PUT", svc.Ping),

		// We can also return errors which will automatically be detected and
		// converted to a HTTP 400 return code to the user. The HTTP return code
		// can be changed by returning a rest.CodedError.
		//
		// The body is returned as a simple string containing the string
		// representation of the error object.
		rest.NewRoute("/ping/error", "POST", svc.PingError),

		// Used for testing the Timeout() feature of a request.
		rest.NewRoute("/ping/delay", "GET", svc.PingDelay),
	}
}

func ExamplePing() {

	// Add our service that implements the rest.Routable interface to our
	// endpoint. We can also add simple lambda functions to our endpoint.
	rest.AddService(new(PingService))
	rest.AddRoute("/simple", "POST", func(tick int) int { return tick })

	// The endpoint is started like any other http.Server.
	go rest.ListenAndServe(":12345", nil)

	time.Sleep(10 * time.Millisecond)

	// The rest package also provides a way to query a REST endpoint by
	// incrementally building a REST request. The body of the query can be set
	// via the SetBody() function which will serialize the object to JSON using
	// the encoding.json package.
	simpleResp := rest.NewRequest("http://localhost:12345", "POST").
		SetPath("/simple").
		SetBody(123).
		Send()

	// The rest.Response object contains the result of the REST request and can
	// be used to deserialize the JSON body into the provided object using the
	// encoding.json package.
	var tick int
	if err := simpleResp.GetBody(&tick); err != nil {
		panic("Whoops!")
	}
	fmt.Println("ping-simple:", tick)

	// The REST client can also be customized by manually creating a rest.Client
	// which can then be used to create REST requests. rest.Client embdeds an
	// http.Client struct which can be used to customize the HTTP requests.
	client := &rest.Client{Host: "http://localhost:12345", Root: "/ping"}
	clientResp := client.NewRequest("PUT").
		SetPath("%d", 321).
		AddParam("test", "321").
		AddParam("test2", "3212").
		Send()

	if err := clientResp.GetBody(&tick); err != nil {
		panic("Whoops!")
	}
	fmt.Println("ping-client:", tick)

	// The REST client can check if a response timed out.
	dialer := net.Dialer{Timeout: 500 * time.Millisecond}
	clientTime := &rest.Client{
		Host: "http://localhost:12345",
		Root: "/ping",
		Client: &http.Client{
			Transport: &http.Transport{Dial: dialer.Dial},
			Timeout:   500 * time.Millisecond,
		},
	}
	timeoutResp := clientTime.NewRequest("GET").
		SetPath("delay").
		Send()

	if err := timeoutResp.GetBody(&tick); err.Type != rest.TimeoutError {
		panic("Whoops! Should time out" + fmt.Sprint(tick))
	}

	// Output:
	// ping-simple: 123
	// ping-client: 321
}
<|endoftext|>


<commit_before>package rethinkstore

import (
	"bytes"
	"encoding/gob"
	"net/http"
	"testing"

	r "github.com/dancannon/gorethink"
	"github.com/gorilla/sessions"
)

var (
	TestDatabase string = "session_test_db"
	TestTable    string = "session_test_table"
)

// ----------------------------------------------------------------------------
// ResponseRecorder
// ----------------------------------------------------------------------------
// Copyright 2009 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.

// ResponseRecorder is an implementation of http.ResponseWriter that
// records its mutations for later inspection in tests.
type ResponseRecorder struct {
	Code      int           // the HTTP response code from WriteHeader
	HeaderMap http.Header   // the HTTP response headers
	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
	Flushed   bool
}

// NewRecorder returns an initialized ResponseRecorder.
func NewRecorder() *ResponseRecorder {
	return &ResponseRecorder{
		HeaderMap: make(http.Header),
		Body:      new(bytes.Buffer),
	}
}

// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
const DefaultRemoteAddr = "1.2.3.4"

// Header returns the response headers.
func (rw *ResponseRecorder) Header() http.Header {
	return rw.HeaderMap
}

// Write always succeeds and writes to rw.Body, if not nil.
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
	if rw.Body != nil {
		rw.Body.Write(buf)
	}
	if rw.Code == 0 {
		rw.Code = http.StatusOK
	}
	return len(buf), nil
}

// WriteHeader sets rw.Code.
func (rw *ResponseRecorder) WriteHeader(code int) {
	rw.Code = code
}

// Flush sets rw.Flushed to true.
func (rw *ResponseRecorder) Flush() {
	rw.Flushed = true
}

// ----------------------------------------------------------------------------

func rethinkSession() *r.Session {
	session, err := r.Connect(r.ConnectOpts{
		Address:  "127.0.0.1:28015",
		Database: TestDatabase,
		MaxIdle:  5,
		MaxOpen:  5,
	})
	if err != nil {
		panic(err)
	}
	return session
}

func Setup() error {
	if err := r.DbCreate(TestDatabase).Exec(rethinkSession()); err != nil {
		return err
	}
	return r.Db(TestDatabase).TableCreate(TestTable).Exec(rethinkSession())
}

func Teardown() error {
	if err := r.Db(TestDatabase).TableDrop(TestTable).Exec(rethinkSession()); err != nil {
		return err
	}
	return r.DbDrop(TestDatabase).Exec(rethinkSession())
}

type FlashMessage struct {
	Type    int
	Message string
}

func TestRethinkStore(t *testing.T) {
	var req *http.Request
	var rsp *ResponseRecorder
	var hdr http.Header
	var err error
	var ok bool
	var cookies []string
	var session *sessions.Session
	var flashes []interface{}

	// Copyright 2012 The Gorilla Authors. All rights reserved.
	// Use of this source code is governed by a BSD-style
	// license that can be found in the LICENSE file.

	if err := Setup(); err != nil {
		panic(err)
	}

	// Round 1 ----------------------------------------------------------------

	// RethinkStore
	store, err := NewRethinkStore("127.0.0.1:28015", TestDatabase, TestTable, 5, 5, []byte("secret-key"))
	if err != nil {
		t.Fatalf(err.Error())
	}
	defer store.Close()

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Get a flash.
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected empty flashes; Got %v", flashes)
	}
	// Add some flashes.
	session.AddFlash("foo")
	session.AddFlash("bar")
	// Custom key.
	session.AddFlash("baz", "custom_key")
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}
	hdr = rsp.Header()
	cookies, ok = hdr["Set-Cookie"]
	if !ok || len(cookies) != 1 {
		t.Fatalf("No cookies. Header:", hdr)
	}

	// Round 2 ----------------------------------------------------------------

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	req.Header.Add("Cookie", cookies[0])
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Check all saved values.
	flashes = session.Flashes()
	if len(flashes) != 2 {
		t.Fatalf("Expected flashes; Got %v", flashes)
	}
	if flashes[0] != "foo" || flashes[1] != "bar" {
		t.Errorf("Expected foo,bar; Got %v", flashes)
	}
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected dumped flashes; Got %v", flashes)
	}
	// Custom key.
	flashes = session.Flashes("custom_key")
	if len(flashes) != 1 {
		t.Errorf("Expected flashes; Got %v", flashes)
	} else if flashes[0] != "baz" {
		t.Errorf("Expected baz; Got %v", flashes)
	}
	flashes = session.Flashes("custom_key")
	if len(flashes) != 0 {
		t.Errorf("Expected dumped flashes; Got %v", flashes)
	}

	// RethinkStore specific
	// Set MaxAge to -1 to mark for deletion.
	session.Options.MaxAge = -1
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}

	// Round 3 ----------------------------------------------------------------
	// Custom type

	// RethinkStore
	store, err = NewRethinkStore("127.0.0.1:28015", TestDatabase, TestTable, 5, 5, []byte("secret-key"))
	if err != nil {
		panic(err)
	}
	defer store.Close()

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Get a flash.
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected empty flashes; Got %v", flashes)
	}
	// Add some flashes.
	session.AddFlash(&FlashMessage{42, "foo"})
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}
	hdr = rsp.Header()
	cookies, ok = hdr["Set-Cookie"]
	if !ok || len(cookies) != 1 {
		t.Fatalf("No cookies. Header:", hdr)
	}

	// Round 4 ----------------------------------------------------------------
	// Custom type

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	req.Header.Add("Cookie", cookies[0])
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Check all saved values.
	flashes = session.Flashes()
	if len(flashes) != 1 {
		t.Fatalf("Expected flashes; Got %v", flashes)
	}
	custom := flashes[0].(FlashMessage)
	if custom.Type != 42 || custom.Message != "foo" {
		t.Errorf("Expected %#v, got %#v", FlashMessage{42, "foo"}, custom)
	}

	// RethinkStore specific
	// Set MaxAge to -1 to mark for deletion.
	session.Options.MaxAge = -1
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}

	if err := Teardown(); err != nil {
		panic(err)
	}
}

func ExampleRethinkStore() {
	// RethinkStore
	store, err := NewRethinkStore("127.0.0.1:28015", TestDatabase, TestTable, 5, 5, []byte("secret-key"))
	if err != nil {
		panic(err)
	}
	defer store.Close()
}

func init() {
	gob.Register(FlashMessage{})
}
<commit_msg>Fixed build break<commit_after>package rethinkstore

import (
	"bytes"
	"encoding/gob"
	"net/http"
	"testing"

	r "github.com/dancannon/gorethink"
	"github.com/gorilla/sessions"
)

var (
	TestDatabase string = "session_test_db"
	TestTable    string = "session_test_table"
)

// ----------------------------------------------------------------------------
// ResponseRecorder
// ----------------------------------------------------------------------------
// Copyright 2009 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.

// ResponseRecorder is an implementation of http.ResponseWriter that
// records its mutations for later inspection in tests.
type ResponseRecorder struct {
	Code      int           // the HTTP response code from WriteHeader
	HeaderMap http.Header   // the HTTP response headers
	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
	Flushed   bool
}

// NewRecorder returns an initialized ResponseRecorder.
func NewRecorder() *ResponseRecorder {
	return &ResponseRecorder{
		HeaderMap: make(http.Header),
		Body:      new(bytes.Buffer),
	}
}

// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
const DefaultRemoteAddr = "1.2.3.4"

// Header returns the response headers.
func (rw *ResponseRecorder) Header() http.Header {
	return rw.HeaderMap
}

// Write always succeeds and writes to rw.Body, if not nil.
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
	if rw.Body != nil {
		rw.Body.Write(buf)
	}
	if rw.Code == 0 {
		rw.Code = http.StatusOK
	}
	return len(buf), nil
}

// WriteHeader sets rw.Code.
func (rw *ResponseRecorder) WriteHeader(code int) {
	rw.Code = code
}

// Flush sets rw.Flushed to true.
func (rw *ResponseRecorder) Flush() {
	rw.Flushed = true
}

// ----------------------------------------------------------------------------

func rethinkSession() *r.Session {
	session, err := r.Connect(r.ConnectOpts{
		Address:  "127.0.0.1:28015",
		Database: TestDatabase,
		MaxIdle:  5,
		MaxOpen:  5,
	})
	if err != nil {
		panic(err)
	}
	return session
}

func Setup() error {
	if err := r.DBCreate(TestDatabase).Exec(rethinkSession()); err != nil {
		return err
	}
	return r.DB(TestDatabase).TableCreate(TestTable).Exec(rethinkSession())
}

func Teardown() error {
	if err := r.DB(TestDatabase).TableDrop(TestTable).Exec(rethinkSession()); err != nil {
		return err
	}
	return r.DBDrop(TestDatabase).Exec(rethinkSession())
}

type FlashMessage struct {
	Type    int
	Message string
}

func TestRethinkStore(t *testing.T) {
	var req *http.Request
	var rsp *ResponseRecorder
	var hdr http.Header
	var err error
	var ok bool
	var cookies []string
	var session *sessions.Session
	var flashes []interface{}

	// Copyright 2012 The Gorilla Authors. All rights reserved.
	// Use of this source code is governed by a BSD-style
	// license that can be found in the LICENSE file.

	if err := Setup(); err != nil {
		panic(err)
	}

	// Round 1 ----------------------------------------------------------------

	// RethinkStore
	store, err := NewRethinkStore("127.0.0.1:28015", TestDatabase, TestTable, 5, 5, []byte("secret-key"))
	if err != nil {
		t.Fatalf(err.Error())
	}
	defer store.Close()

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Get a flash.
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected empty flashes; Got %v", flashes)
	}
	// Add some flashes.
	session.AddFlash("foo")
	session.AddFlash("bar")
	// Custom key.
	session.AddFlash("baz", "custom_key")
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}
	hdr = rsp.Header()
	cookies, ok = hdr["Set-Cookie"]
	if !ok || len(cookies) != 1 {
		t.Fatalf("No cookies. Header:", hdr)
	}

	// Round 2 ----------------------------------------------------------------

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	req.Header.Add("Cookie", cookies[0])
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Check all saved values.
	flashes = session.Flashes()
	if len(flashes) != 2 {
		t.Fatalf("Expected flashes; Got %v", flashes)
	}
	if flashes[0] != "foo" || flashes[1] != "bar" {
		t.Errorf("Expected foo,bar; Got %v", flashes)
	}
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected dumped flashes; Got %v", flashes)
	}
	// Custom key.
	flashes = session.Flashes("custom_key")
	if len(flashes) != 1 {
		t.Errorf("Expected flashes; Got %v", flashes)
	} else if flashes[0] != "baz" {
		t.Errorf("Expected baz; Got %v", flashes)
	}
	flashes = session.Flashes("custom_key")
	if len(flashes) != 0 {
		t.Errorf("Expected dumped flashes; Got %v", flashes)
	}

	// RethinkStore specific
	// Set MaxAge to -1 to mark for deletion.
	session.Options.MaxAge = -1
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}

	// Round 3 ----------------------------------------------------------------
	// Custom type

	// RethinkStore
	store, err = NewRethinkStore("127.0.0.1:28015", TestDatabase, TestTable, 5, 5, []byte("secret-key"))
	if err != nil {
		panic(err)
	}
	defer store.Close()

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Get a flash.
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected empty flashes; Got %v", flashes)
	}
	// Add some flashes.
	session.AddFlash(&FlashMessage{42, "foo"})
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}
	hdr = rsp.Header()
	cookies, ok = hdr["Set-Cookie"]
	if !ok || len(cookies) != 1 {
		t.Fatalf("No cookies. Header:", hdr)
	}

	// Round 4 ----------------------------------------------------------------
	// Custom type

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	req.Header.Add("Cookie", cookies[0])
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Check all saved values.
	flashes = session.Flashes()
	if len(flashes) != 1 {
		t.Fatalf("Expected flashes; Got %v", flashes)
	}
	custom := flashes[0].(FlashMessage)
	if custom.Type != 42 || custom.Message != "foo" {
		t.Errorf("Expected %#v, got %#v", FlashMessage{42, "foo"}, custom)
	}

	// RethinkStore specific
	// Set MaxAge to -1 to mark for deletion.
	session.Options.MaxAge = -1
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}

	if err := Teardown(); err != nil {
		panic(err)
	}
}

func ExampleRethinkStore() {
	// RethinkStore
	store, err := NewRethinkStore("127.0.0.1:28015", TestDatabase, TestTable, 5, 5, []byte("secret-key"))
	if err != nil {
		panic(err)
	}
	defer store.Close()
}

func init() {
	gob.Register(FlashMessage{})
}
<|endoftext|>


<commit_before>package jsonschema

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// primitiveTypes is a map of strings to check types against
var primitiveTypes = map[string]bool{
	"null":    true,
	"boolean": true,
	"object":  true,
	"array":   true,
	"number":  true,
	"string":  true,
	"integer": true,
}

// DataType gives the primitive json type of a standard json-decoded value, plus the special case
// "integer" for when numbers are whole
func DataType(data interface{}) string {
	switch v := data.(type) {
	case nil:
		return "null"
	case bool:
		return "boolean"
	case float64:
		if float64(int(v)) == v {
			return "integer"
		}
		return "number"
	case string:
		return "string"
	case []interface{}:
		return "array"
	case map[string]interface{}:
		return "object"
	default:
		return "unknown"
	}
}

// Type specifies one of the six json primitive types.
// The value of this keyword MUST be either a string or an array.
// If it is an array, elements of the array MUST be strings and MUST be unique.
// String values MUST be one of the six primitive types ("null", "boolean", "object", "array", "number", or "string"), or
// "integer" which matches any number with a zero fractional part.
// An instance validates if and only if the instance is in any of the sets listed for this keyword.
type Type struct {
	BaseValidator
	strVal bool // set to true if Type decoded from a string, false if an array
	vals   []string
}

// NewType creates a new Type Validator
func NewType() Validator {
	return &Type{}
}

// String returns the type(s) as a string, or unknown if there is no known type.
func (t Type) String() string {
	if len(t.vals) == 0 {
		return "unknown"
	}
	return strings.Join(t.vals, ",")
}

// Validate checks to see if input data satisfies the type constraint
func (t Type) Validate(propPath string, data interface{}, errs *[]ValError) {
	jt := DataType(data)
	for _, typestr := range t.vals {
		if jt == typestr || jt == "integer" && typestr == "number" {
			return
		}
	}
	if len(t.vals) == 1 {
		t.AddError(errs, propPath, data, fmt.Sprintf(`type should be %s`, t.vals[0]))
		return
	}

	str := ""
	for _, ts := range t.vals {
		str += ts + ","
	}

	t.AddError(errs, propPath, data, fmt.Sprintf(`type should be one of: %s`, str[:len(str)-1]))
}

// JSONProp implements JSON property name indexing for Type
func (t Type) JSONProp(name string) interface{} {
	idx, err := strconv.Atoi(name)
	if err != nil {
		return nil
	}
	if idx > len(t.vals) || idx < 0 {
		return nil
	}
	return t.vals[idx]
}

// UnmarshalJSON implements the json.Unmarshaler interface for Type
func (t *Type) UnmarshalJSON(data []byte) error {
	var single string
	if err := json.Unmarshal(data, &single); err == nil {
		*t = Type{strVal: true, vals: []string{single}}
	} else {
		var set []string
		if err := json.Unmarshal(data, &set); err == nil {
			*t = Type{vals: set}
		} else {
			return err
		}
	}

	for _, pr := range t.vals {
		if !primitiveTypes[pr] {
			return fmt.Errorf(`"%s" is not a valid type`, pr)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaler interface for Type
func (t Type) MarshalJSON() ([]byte, error) {
	if t.strVal {
		return json.Marshal(t.vals[0])
	}
	return json.Marshal(t.vals)
}

// Enum validates successfully against this keyword if its value is equal to one of the
// elements in this keyword's array value.
// Elements in the array SHOULD be unique.
// Elements in the array might be of any value, including null.
type Enum []Const

// NewEnum creates a new Enum Validator
func NewEnum() Validator {
	return &Enum{}
}

// String implements the stringer interface for Enum
func (e Enum) String() string {
	str := "["
	for _, c := range e {
		str += c.String() + ", "
	}
	return str[:len(str)-2] + "]"
}

// Path gives a jsonpointer path to the validator
func (e Enum) Path() string {
	return ""
}

// Validate implements the Validator interface for Enum
func (e Enum) Validate(propPath string, data interface{}, errs *[]ValError) {
	for _, v := range e {
		test := &[]ValError{}
		v.Validate(propPath, data, test)
		if len(*test) == 0 {
			return
		}
	}

	AddError(errs, propPath, data, fmt.Sprintf("should be one of %s", e.String()))
}

// JSONProp implements JSON property name indexing for Enum
func (e Enum) JSONProp(name string) interface{} {
	idx, err := strconv.Atoi(name)
	if err != nil {
		return nil
	}
	if idx > len(e) || idx < 0 {
		return nil
	}
	return e[idx]
}

// JSONChildren implements the JSONContainer interface for Enum
func (e Enum) JSONChildren() (res map[string]JSONPather) {
	res = map[string]JSONPather{}
	for i, bs := range e {
		res[strconv.Itoa(i)] = bs
	}
	return
}

// Const MAY be of any type, including null.
// An instance validates successfully against this keyword if its
// value is equal to the value of the keyword.
type Const json.RawMessage

// NewConst creates a new Const Validator
func NewConst() Validator {
	return &Const{}
}

// Path gives a jsonpointer path to the validator
func (c Const) Path() string {
	return ""
}

// Validate implements the validate interface for Const
func (c Const) Validate(propPath string, data interface{}, errs *[]ValError) {
	var con interface{}
	if err := json.Unmarshal(c, &con); err != nil {
		AddError(errs, propPath, data, err.Error())
		return
	}

	if !reflect.DeepEqual(con, data) {
		AddError(errs, propPath, data, fmt.Sprintf(`must equal %s`, InvalidValueString(data)))
	}
}

// JSONProp implements JSON property name indexing for Const
func (c Const) JSONProp(name string) interface{} {
	return nil
}

// String implements the Stringer interface for Const
func (c Const) String() string {
	return string(c)
}

// UnmarshalJSON implements the json.Unmarshaler interface for Const
func (c *Const) UnmarshalJSON(data []byte) error {
	*c = data
	return nil
}

// MarshalJSON implements json.Marshaler for Const
func (c Const) MarshalJSON() ([]byte, error) {
	return json.Marshal(json.RawMessage(c))
}
<commit_msg>fix(const error): error reports what const must equal instead of supplied value<commit_after>package jsonschema

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// primitiveTypes is a map of strings to check types against
var primitiveTypes = map[string]bool{
	"null":    true,
	"boolean": true,
	"object":  true,
	"array":   true,
	"number":  true,
	"string":  true,
	"integer": true,
}

// DataType gives the primitive json type of a standard json-decoded value, plus the special case
// "integer" for when numbers are whole
func DataType(data interface{}) string {
	switch v := data.(type) {
	case nil:
		return "null"
	case bool:
		return "boolean"
	case float64:
		if float64(int(v)) == v {
			return "integer"
		}
		return "number"
	case string:
		return "string"
	case []interface{}:
		return "array"
	case map[string]interface{}:
		return "object"
	default:
		return "unknown"
	}
}

// Type specifies one of the six json primitive types.
// The value of this keyword MUST be either a string or an array.
// If it is an array, elements of the array MUST be strings and MUST be unique.
// String values MUST be one of the six primitive types ("null", "boolean", "object", "array", "number", or "string"), or
// "integer" which matches any number with a zero fractional part.
// An instance validates if and only if the instance is in any of the sets listed for this keyword.
type Type struct {
	BaseValidator
	strVal bool // set to true if Type decoded from a string, false if an array
	vals   []string
}

// NewType creates a new Type Validator
func NewType() Validator {
	return &Type{}
}

// String returns the type(s) as a string, or unknown if there is no known type.
func (t Type) String() string {
	if len(t.vals) == 0 {
		return "unknown"
	}
	return strings.Join(t.vals, ",")
}

// Validate checks to see if input data satisfies the type constraint
func (t Type) Validate(propPath string, data interface{}, errs *[]ValError) {
	jt := DataType(data)
	for _, typestr := range t.vals {
		if jt == typestr || jt == "integer" && typestr == "number" {
			return
		}
	}
	if len(t.vals) == 1 {
		t.AddError(errs, propPath, data, fmt.Sprintf(`type should be %s`, t.vals[0]))
		return
	}

	str := ""
	for _, ts := range t.vals {
		str += ts + ","
	}

	t.AddError(errs, propPath, data, fmt.Sprintf(`type should be one of: %s`, str[:len(str)-1]))
}

// JSONProp implements JSON property name indexing for Type
func (t Type) JSONProp(name string) interface{} {
	idx, err := strconv.Atoi(name)
	if err != nil {
		return nil
	}
	if idx > len(t.vals) || idx < 0 {
		return nil
	}
	return t.vals[idx]
}

// UnmarshalJSON implements the json.Unmarshaler interface for Type
func (t *Type) UnmarshalJSON(data []byte) error {
	var single string
	if err := json.Unmarshal(data, &single); err == nil {
		*t = Type{strVal: true, vals: []string{single}}
	} else {
		var set []string
		if err := json.Unmarshal(data, &set); err == nil {
			*t = Type{vals: set}
		} else {
			return err
		}
	}

	for _, pr := range t.vals {
		if !primitiveTypes[pr] {
			return fmt.Errorf(`"%s" is not a valid type`, pr)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaler interface for Type
func (t Type) MarshalJSON() ([]byte, error) {
	if t.strVal {
		return json.Marshal(t.vals[0])
	}
	return json.Marshal(t.vals)
}

// Enum validates successfully against this keyword if its value is equal to one of the
// elements in this keyword's array value.
// Elements in the array SHOULD be unique.
// Elements in the array might be of any value, including null.
type Enum []Const

// NewEnum creates a new Enum Validator
func NewEnum() Validator {
	return &Enum{}
}

// String implements the stringer interface for Enum
func (e Enum) String() string {
	str := "["
	for _, c := range e {
		str += c.String() + ", "
	}
	return str[:len(str)-2] + "]"
}

// Path gives a jsonpointer path to the validator
func (e Enum) Path() string {
	return ""
}

// Validate implements the Validator interface for Enum
func (e Enum) Validate(propPath string, data interface{}, errs *[]ValError) {
	for _, v := range e {
		test := &[]ValError{}
		v.Validate(propPath, data, test)
		if len(*test) == 0 {
			return
		}
	}

	AddError(errs, propPath, data, fmt.Sprintf("should be one of %s", e.String()))
}

// JSONProp implements JSON property name indexing for Enum
func (e Enum) JSONProp(name string) interface{} {
	idx, err := strconv.Atoi(name)
	if err != nil {
		return nil
	}
	if idx > len(e) || idx < 0 {
		return nil
	}
	return e[idx]
}

// JSONChildren implements the JSONContainer interface for Enum
func (e Enum) JSONChildren() (res map[string]JSONPather) {
	res = map[string]JSONPather{}
	for i, bs := range e {
		res[strconv.Itoa(i)] = bs
	}
	return
}

// Const MAY be of any type, including null.
// An instance validates successfully against this keyword if its
// value is equal to the value of the keyword.
type Const json.RawMessage

// NewConst creates a new Const Validator
func NewConst() Validator {
	return &Const{}
}

// Path gives a jsonpointer path to the validator
func (c Const) Path() string {
	return ""
}

// Validate implements the validate interface for Const
func (c Const) Validate(propPath string, data interface{}, errs *[]ValError) {
	var con interface{}
	if err := json.Unmarshal(c, &con); err != nil {
		AddError(errs, propPath, data, err.Error())
		return
	}

	if !reflect.DeepEqual(con, data) {
		AddError(errs, propPath, data, fmt.Sprintf(`must equal %s`, InvalidValueString(con)))
	}
}

// JSONProp implements JSON property name indexing for Const
func (c Const) JSONProp(name string) interface{} {
	return nil
}

// String implements the Stringer interface for Const
func (c Const) String() string {
	return string(c)
}

// UnmarshalJSON implements the json.Unmarshaler interface for Const
func (c *Const) UnmarshalJSON(data []byte) error {
	*c = data
	return nil
}

// MarshalJSON implements json.Marshaler for Const
func (c Const) MarshalJSON() ([]byte, error) {
	return json.Marshal(json.RawMessage(c))
}
<|endoftext|>