<commit_before>// Package transcription implements functions for the manipulation and
// transcription of audio files.
package transcription

import (
	"fmt"
	"io"
	"net/http"
	"net/smtp"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/jordan-wright/email"
	"github.com/juju/errors"

	"github.com/hack4impact/transcribe4all/config"
)

// SendEmail connects to an email server at host:port and sends an email from
// address from, to address to, with subject line subject with message body.
func SendEmail(username string, password string, host string, port int, to []string, subject string, body string) error {
	auth := smtp.PlainAuth("", username, password, host)
	addr := host + ":" + strconv.Itoa(port)

	message := email.Email{
		From:    username,
		To:      to,
		Subject: subject,
		Text:    []byte(body),
	}
	if err := message.Send(addr, auth); err != nil {
		return errors.Trace(err)
	}
	return nil
}

// ConvertAudioIntoFormat converts encoded audio into the required format.
func ConvertAudioIntoFormat(filePath, fileExt string) (string, error) {
	// http://cmusphinx.sourceforge.net/wiki/faq
	// -ar 16000 sets frequency to required 16khz
	// -ac 1 sets the number of audio channels to 1
	newPath := filePath + "." + fileExt
	os.Remove(newPath) // If it already exists, ffmpeg will throw an error
	cmd := exec.Command("ffmpeg", "-i", filePath, "-ar", "16000", "-ac", "1", newPath)
	if out, err := cmd.CombinedOutput(); err != nil {
		return "", errors.New(err.Error() + "\nCommand Output:" + string(out))
	}
	return newPath, nil
}

// DownloadFileFromURL locally downloads an audio file stored at url.
func DownloadFileFromURL(url string) (string, error) {
	// Taken from https://github.com/thbar/golang-playground/blob/master/download-files.go
	filePath := filePathFromURL(url)
	file, err := os.Create(filePath)
	if err != nil {
		return "", errors.Trace(err)
	}
	defer file.Close()

	// Get file contents
	response, err := http.Get(url)
	if err != nil {
		return "", errors.Trace(err)
	}
	defer response.Body.Close()

	// Write the body to file
	_, err = io.Copy(file, response.Body)
	if err != nil {
		return "", errors.Trace(err)
	}

	return filePath, nil
}

func filePathFromURL(url string) string {
	tokens := strings.Split(url, "/")
	filePath := tokens[len(tokens)-1]
	// ensure the filePath is unique by appending timestamp
	filePath = filePath + strconv.Itoa(int(time.Now().UnixNano()))
	return filePath
}

// SplitFlacFile ensures that the input audio files to IBM are less than 100mb, with 5 seconds of redundancy between files.
func SplitFlacFile(fn string) error {
	// http://stackoverflow.com/questions/36632511/split-audio-file-into-several-files-each-below-a-size-threshold
	// The Stack Overflow answer ultimately calculated the length of each audio chunk in seconds.
	// chunk_length_in_sec = math.ceil((duration_in_sec * file_split_size ) / wav_file_size)
	// Invariant: If ConvertAudioIntoWavFormat is called on fn, a 95MB chunk of resulting Wav file is always 2968 seconds.
	// In the above equation, there is one constant: file_split_size = 95000000 bytes.
	// duration_in_sec is used to calculate wav_file_size, so it is canceled out in the ratio.
	// wav_file_size = (sample_rate * bit_rate * channel_count * duration_in_sec) / 8
	// sample_rate = 44100, bit_rate = 16, channels_count = 1 (stereo: 2, but Sphinx prefers 1)
	// As a chunk of the Wav file is extracted using FFMPEG, it is converted back into Flac format.
	wavFileName, err := ConvertAudioIntoFormat(fn, "wav")
	if err != nil {
		return err
	}

	numChunks, err := getNumChunks(fn)
	if err != nil {
		return err
	}

	chunkLengthInSeconds := 2968
	for i := 0; i < numChunks; i++ {
		// 5 seconds of redundancy for each chunk after the first
		startingSecond := i*chunkLengthInSeconds - (i-1)*5
		newFileName := wavFileName + strconv.Itoa(i)
		if err := extractAudioSegment(newFileName, startingSecond, chunkLengthInSeconds); err != nil {
			return err
		}
		if _, err := ConvertAudioIntoFormat(newFileName, "flac"); err != nil {
			return err
		}
	}
	return nil
}

// getNumChunks gets file size in MB, divides by 95 MB, and add 1 more chunk in case
func getNumChunks(fn string) (int, error) {
	file, err := os.Open(fn)
	if err != nil {
		return -1, err
	}
	defer file.Close()

	stat, err := file.Stat()
	if err != nil {
		return -1, err
	}

	wavFileSize := int(stat.Size())
	fileSplitSize := 95000000
	// The redundant seconds (5 seconds for every ~50 mintues) won't add own chunk
	// In case the remainder is almost the file size, add one more chunk
	numChunks := wavFileSize/fileSplitSize + 1
	return numChunks, nil
}

// extractAudioSegment uses FFMPEG to write a new audio file starting at a given time of a given length
func extractAudioSegment(fn string, ss int, t int) error {
	// -ss: starting second, -t: time in seconds
	cmd := exec.Command("ffmpeg", "-i", fn, "-ss", strconv.Itoa(ss), "-t", strconv.Itoa(t), fn)
	if err := cmd.Run(); err != nil {
		return err
	}
	return nil
}

// MakeIBMTaskFunction returns a task function for transcription using IBM transcription functions.
func MakeIBMTaskFunction(audioURL string, emailAddresses []string, searchWords []string) (task func(string) error, onFailure func(string, string)) {
	task = func(id string) error {
		filePath, err := DownloadFileFromURL(audioURL)
		if err != nil {
			return errors.Trace(err)
		}
		defer os.Remove(filePath)

		log.WithField("task", id).
			Debugf("Downloaded file at %s to %s", audioURL, filePath)

		flacPath, err := ConvertAudioIntoFormat(filePath, "flac")
		if err != nil {
			return errors.Trace(err)
		}
		defer os.Remove(flacPath)

		log.WithField("task", id).
			Debugf("Converted file %s to %s", filePath, flacPath)

		ibmResult, err := TranscribeWithIBM(flacPath, config.Config.IBMUsername, config.Config.IBMPassword)
		if err != nil {
			return errors.Trace(err)
		}
		transcript := GetTranscript(ibmResult)

		log.WithField("task", id).
			Info(transcript)

		// TODO: save data to MongoDB and file to Backblaze.

		if err := SendEmail(config.Config.EmailUsername, config.Config.EmailPassword, "smtp.gmail.com", 25, emailAddresses, fmt.Sprintf("IBM Transcription %s Complete", id), "The transcript is below. It can also be found in the database."+"\n\n"+transcript); err != nil {
			return errors.Trace(err)
		}

		log.WithField("task", id).
			Debugf("Sent email to %v", emailAddresses)

		return nil
	}

	onFailure = func(id string, errMessage string) {
		err := SendEmail(config.Config.EmailUsername, config.Config.EmailPassword, "smtp.gmail.com", 25, emailAddresses, fmt.Sprintf("IBM Transcription %s Failed", id), errMessage)
		if err != nil {
			log.WithField("task", id).
				Debugf("Could not send error email to %v because of the error %v", emailAddresses, err.Error())
			return
		}
		log.WithField("task", id).
			Debugf("Sent email to %v", emailAddresses)
	}
	return task, onFailure
}
<commit_msg>Caller will convert to/from wav; fn->fileName; split returns slice of file names<commit_after>// Package transcription implements functions for the manipulation and
// transcription of audio files.
package transcription

import (
	"fmt"
	"io"
	"net/http"
	"net/smtp"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/jordan-wright/email"
	"github.com/juju/errors"

	"github.com/hack4impact/transcribe4all/config"
)

// SendEmail connects to an email server at host:port and sends an email from
// address from, to address to, with subject line subject with message body.
func SendEmail(username string, password string, host string, port int, to []string, subject string, body string) error {
	auth := smtp.PlainAuth("", username, password, host)
	addr := host + ":" + strconv.Itoa(port)

	message := email.Email{
		From:    username,
		To:      to,
		Subject: subject,
		Text:    []byte(body),
	}
	if err := message.Send(addr, auth); err != nil {
		return errors.Trace(err)
	}
	return nil
}

// ConvertAudioIntoFormat converts encoded audio into the required format.
func ConvertAudioIntoFormat(filePath, fileExt string) (string, error) {
	// http://cmusphinx.sourceforge.net/wiki/faq
	// -ar 16000 sets frequency to required 16khz
	// -ac 1 sets the number of audio channels to 1
	newPath := filePath + "." + fileExt
	os.Remove(newPath) // If it already exists, ffmpeg will throw an error
	cmd := exec.Command("ffmpeg", "-i", filePath, "-ar", "16000", "-ac", "1", newPath)
	if out, err := cmd.CombinedOutput(); err != nil {
		return "", errors.New(err.Error() + "\nCommand Output:" + string(out))
	}
	return newPath, nil
}

// DownloadFileFromURL locally downloads an audio file stored at url.
func DownloadFileFromURL(url string) (string, error) {
	// Taken from https://github.com/thbar/golang-playground/blob/master/download-files.go
	filePath := filePathFromURL(url)
	file, err := os.Create(filePath)
	if err != nil {
		return "", errors.Trace(err)
	}
	defer file.Close()

	// Get file contents
	response, err := http.Get(url)
	if err != nil {
		return "", errors.Trace(err)
	}
	defer response.Body.Close()

	// Write the body to file
	_, err = io.Copy(file, response.Body)
	if err != nil {
		return "", errors.Trace(err)
	}

	return filePath, nil
}

func filePathFromURL(url string) string {
	tokens := strings.Split(url, "/")
	filePath := tokens[len(tokens)-1]
	// ensure the filePath is unique by appending timestamp
	filePath = filePath + strconv.Itoa(int(time.Now().UnixNano()))
	return filePath
}

// SplitWavFile ensures that the input audio files to IBM are less than 100mb, with 5 seconds of redundancy between files.
func SplitWavFile(wavFileName string) ([]string, error) {
	// http://stackoverflow.com/questions/36632511/split-audio-file-into-several-files-each-below-a-size-threshold
	// The Stack Overflow answer ultimately calculated the length of each audio chunk in seconds.
	// chunk_length_in_sec = math.ceil((duration_in_sec * file_split_size ) / wav_file_size)
	// Invariant: If ConvertAudioIntoWavFormat is called on filePath, a 95MB chunk of resulting Wav file is always 2968 seconds.
	// In the above equation, there is one constant: file_split_size = 95000000 bytes.
	// duration_in_sec is used to calculate wav_file_size, so it is canceled out in the ratio.
	// wav_file_size = (sample_rate * bit_rate * channel_count * duration_in_sec) / 8
	// sample_rate = 44100, bit_rate = 16, channels_count = 1 (stereo: 2, but Sphinx prefers 1)
	// As a chunk of the Wav file is extracted using FFMPEG, it is converted back into Flac format.
	numChunks, err := getNumChunks(wavFileName)
	if err != nil {
		return []string{}, err
	}

	chunkLengthInSeconds := 2968
	names := make([]string, numChunks)
	for i := 0; i < numChunks; i++ {
		// 5 seconds of redundancy for each chunk after the first
		startingSecond := i*chunkLengthInSeconds - (i-1)*5
		newFileName := wavFileName + strconv.Itoa(i)
		if err := extractAudioSegment(newFileName, startingSecond, chunkLengthInSeconds); err != nil {
			return []string{}, err
		}
		if _, err := ConvertAudioIntoFormat(newFileName, "flac"); err != nil {
			return []string{}, err
		}
		names[i] = newFileName
	}

	return names, nil
}

// getNumChunks gets file size in MB, divides by 95 MB, and add 1 more chunk in case
func getNumChunks(filePath string) (int, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return -1, err
	}
	defer file.Close()

	stat, err := file.Stat()
	if err != nil {
		return -1, err
	}

	wavFileSize := int(stat.Size())
	fileSplitSize := 95000000
	// The redundant seconds (5 seconds for every ~50 mintues) won't add own chunk
	// In case the remainder is almost the file size, add one more chunk
	numChunks := wavFileSize/fileSplitSize + 1
	return numChunks, nil
}

// extractAudioSegment uses FFMPEG to write a new audio file starting at a given time of a given length
func extractAudioSegment(filePath string, ss int, t int) error {
	// -ss: starting second, -t: time in seconds
	cmd := exec.Command("ffmpeg", "-i", filePath, "-ss", strconv.Itoa(ss), "-t", strconv.Itoa(t), filePath)
	if err := cmd.Run(); err != nil {
		return err
	}
	return nil
}

// MakeIBMTaskFunction returns a task function for transcription using IBM transcription functions.
func MakeIBMTaskFunction(audioURL string, emailAddresses []string, searchWords []string) (task func(string) error, onFailure func(string, string)) {
	task = func(id string) error {
		filePath, err := DownloadFileFromURL(audioURL)
		if err != nil {
			return errors.Trace(err)
		}
		defer os.Remove(filePath)

		log.WithField("task", id).
			Debugf("Downloaded file at %s to %s", audioURL, filePath)

		flacPath, err := ConvertAudioIntoFormat(filePath, "flac")
		if err != nil {
			return errors.Trace(err)
		}
		defer os.Remove(flacPath)

		log.WithField("task", id).
			Debugf("Converted file %s to %s", filePath, flacPath)

		wavPath, err := ConvertAudioIntoFormat(filePath, "wav")
		if err != nil {
			return errors.Trace(err)
		}
		defer os.Remove(wavPath)

		log.WithField("task", id).
			Debugf("Converted file %s to %s", flacPath, wavPath)

		ibmResult, err := TranscribeWithIBM(flacPath, config.Config.IBMUsername, config.Config.IBMPassword)
		if err != nil {
			return errors.Trace(err)
		}
		transcript := GetTranscript(ibmResult)

		log.WithField("task", id).
			Info(transcript)

		// TODO: save data to MongoDB and file to Backblaze.

		if err := SendEmail(config.Config.EmailUsername, config.Config.EmailPassword, "smtp.gmail.com", 25, emailAddresses, fmt.Sprintf("IBM Transcription %s Complete", id), "The transcript is below. It can also be found in the database."+"\n\n"+transcript); err != nil {
			return errors.Trace(err)
		}

		log.WithField("task", id).
			Debugf("Sent email to %v", emailAddresses)

		return nil
	}

	onFailure = func(id string, errMessage string) {
		err := SendEmail(config.Config.EmailUsername, config.Config.EmailPassword, "smtp.gmail.com", 25, emailAddresses, fmt.Sprintf("IBM Transcription %s Failed", id), errMessage)
		if err != nil {
			log.WithField("task", id).
				Debugf("Could not send error email to %v because of the error %v", emailAddresses, err.Error())
			return
		}
		log.WithField("task", id).
			Debugf("Sent email to %v", emailAddresses)
	}
	return task, onFailure
}
<|endoftext|>


<commit_before>package ics

import (
	"encoding/base64"
	"errors"
	"io"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/MJKWoolnough/parser"
)

type Binary []byte

func (b *Binary) Decode(params map[string]string, data string) error {
	if params["ENCODING"] != "BASE64" {
		return ErrInvalidEncoding
	}
	cb, err := base64.StdEncoding.DecodeString(data)
	*b = cb
	return err
}

func (b *Binary) Encode(w io.Writer) {
	e := base64.NewEncoder(base64.StdEncoding, w)
	e.Write([]byte(*b))
	e.Close()
}

type Boolean bool

func (b *Boolean) Decode(params map[string]string, data string) error {
	cb, err := strconv.ParseBool(data)
	*b = cb
	return err
}

var (
	booleanTrue  = [...]byte{'T', 'R', 'U', 'E'}
	booleanFalse = [...]byte{'F', 'A', 'L', 'S', 'E'}
)

func (b *Boolean) Encode(w io.Writer) {
	if *b {
		w.Write(booleanTrue[:])
	} else {
		w.Write(booleanFalse[:])
	}
}

type CalAddress struct {
	URI
}

type Date struct {
	time.Time
}

func (d *Date) Decode(params map[string]string, data string) error {
	t, err := time.Parse("20060102", data)
	if err != nil {
		return err
	}
	d.Time = t
	return nil
}

func (d *Date) Encode(w io.Writer) {
	b := make([]byte, 0, 8)
	w.Write([]byte(d.AppendFormat(b, "20060102")))
}

type DateTime struct {
	time.Time
}

func (d *DateTime) Decode(params map[string]string, data string) error {
	if tz, ok := params["TZID"]; ok {
		l, err := time.LoadLocation(tz)
		if err != nil {
			return err
		}
		t, err := time.ParseInLocation("20060102T150405", data, l)
		if err != nil {
			return err
		}
		d.Time = t
	} else if len(data) > 0 && data[len(data)-1] == 'Z' {
		t, err := time.ParseInLocation("20060102T150405Z", data, time.UTC)
		if err != nil {
			return err
		}
		d.Time = t
	} else {
		t, err := time.ParseInLocation("20060102T150405", data, time.Local)
		if err != nil {
			return err
		}
		d.Time = t
	}
	return nil
}

func (d *DateTime) Encode(w io.Writer) {
	b := make([]byte, 0, 16)
	switch d.Location() {
	case time.UTC:
		b = d.AppendFormat(b, "20060102T150405Z")
	case time.Local:
		b = d.AppendFormat(b, "20060102T150405")
	default:
		b = d.AppendFormat(b, "20060102T150405")
	}
	w.Write(b)
}

type Duration struct {
	Negative                             bool
	Weeks, Days, Hours, Minutes, Seconds uint
}

func (d *Duration) Decode(params map[string]string, data string) error {
	t := parser.NewStringTokeniser(data)
	var neg bool
	if t.Accept("-") {
		neg = true
	} else {
		t.Accept("+")
	}
	if !t.Accept("P") {
		return ErrInvalidDuration
	}
	var level uint8
	for t.Peek() != -1 {
		t.Get()
		mode := t.AcceptRun("0123456789")
		num, err := strconv.ParseUint(t.Get(), 10, 0)
		if err != nil {
			return err
		}
		switch mode {
		case 'W':
			t.Accept("W")
			if t.Peek() != -1 {
				return ErrInvalidDuration
			}
			d.Weeks = num
			return nil
		case 'D':
			if level > 0 {
				return ErrInvalidDuration
			}
			t.Accept("D")
			d.Days = num
			level = 1
		case 'H':
			if level > 1 {
				return ErrInvalidDuration
			}
			t.Accept("H")
			d.Hours = num
			level = 2
		case 'M':
			if level > 2 {
				return ErrInvalidDuration
			}
			t.Accept("M")
			d.Minutes = num
			level = 3
		case 'S':
			if level > 3 {
				return ErrInvalidDuration
			}
			t.Accept("S")
			if t.Peek() != -1 {
				return ErrInvalidDuration
			}
			d.Seconds = num
		default:
			return ErrInvalidDuration
		}
	}
	if level == 0 {
		return ErrInvalidDuration
	}
	return nil
}

func itoa(i uint) []byte {
	if i == 0 {
		return []byte{'0'}
	}
	var digits [20]byte
	pos := 20
	for ; n > 0; n /= 10 {
		pos--
		digits[pos] = '0' + byte(n%10)
	}
	return digits[pos:]
}

func (d *Duration) Encode(w io.Writer) {
	data := make([]byte, 0, 64)
	if d.Negative {
		data = append(data, '-')
	}
	data = append(data, 'P')
	if d.Weeks != 0 {
		data = append(data, itoa(d.Weeks)...)
		data = append(data, 'W')
		return nil
	} else {
		if d.Days != 0 {
			data = append(data, itoa(d.Days)...)
			data = append(data, 'D')
		}
		if d.Days == 0 || (d.Hours != 0 || d.Minutes != 0 || d.Seconds != 0) {
			data = append(data, 'T')
			if d.Hours != 0 {
				data = append(data, itoa(d.Hours)...)
				data = append(data, 'H')
				if d.Minutes != 0 || d.Seconds != 0 {
					data = append(data, itoa(d.Minutes)...)
					data = append(data, 'M')
					if d.Seconds != 0 {
						data = append(data, itoa(d.Seconds)...)
						data = append(data, 'S')
					}
				}
			} else if d.Minutes != 0 {
				data = append(data, itoa(d.Minutes)...)
				data = append(data, 'M')
				if d.Seconds != 0 {
					data = append(data, itoa(d.Seconds)...)
					data = append(data, 'S')
				}
			} else {
				data = append(data, itoa(d.Seconds)...)
				data = append(data, 'S')
			}
		}
	}
	w.Write(data)
}

type Float float64

func (f *Float) Decode(params map[string]string, data string) error {
	cf, err := strconv.ParseFloat(data, 64)
	if err != nil {
		return err
	}
	*f = Float(cf)
	return nil
}

func (f *Float) Encode(w io.Writer) {
	w.Write([]byte(strconv.FormatFloat(float64(*f), 'f', 64)))
}

type Integer int32

func (i *Integer) Decode(params map[string]string, data string) error {
	ci, err := strconv.ParseInt(data, 10, 32)
	if err != nil {
		return err
	}
	*i = Integer(ci)
	return nil
}

func (i *Integer) Encode(w io.Writer) {
	w.Write([]byte(strconv.FormatInt(int64(*i), 10)))
}

type Period struct {
	Start, End DateTime
	Duration   Duration
}

func (p *Period) Decode(params map[string]string, data string) error {
	i := strings.IndexByte(data, '/')
	if i == -1 || len(data) == i+1 {
		return ErrInvalidPeriod
	}
	err := p.Start.Decode(params, data[:i])
	if err != nil {
		return err
	}
	if data[i+1] == 'P' || data[i+1] == '+' {
		return p.Duration.Decode(params, data[i+1:])
	}
	return p.End.Decode(params, data[i+1:])
}

func (p *Period) Encode(w io.Writer) {
	p.Start.Encode(w)
	w.Write([]byte{'/'})
	if p.End.IsZero() {
		p.Duration.Encode(w)
	} else {
		p.End.Encode(w)
	}
}

type Recur struct {
}

func (r *Recur) Decode(params map[string]string, data string) error {
	return nil
}

func (r *Recur) Encode(w io.Writer) {

}

type Text string

func (t *Text) Decode(params map[string]string, data string) error {
	return nil
}

func (t *Text) Encode(w io.Writer) {

}

type Time struct {
	time.Time
}

func (t *Time) Decode(params map[string]string, data string) error {
	return nil
}

func (t *Time) Encode(w io.Writer) {

}

type URI struct {
	url.URL
}

func (u *URI) Decode(params map[string]string, data string) error {
	cu, err := url.Parse(data)
	if err != nil {
		return err
	}
	u.URL = cu
	return nil
}

func (u *URI) Encode(w io.Writer) {
	w.Write([]byte(u.URL.String()))
}

type UTCOffset int

func (u *UTCOffset) Decode(params map[string]string, data string) error {
	return nil
}

func (u *UTCOffset) Encode(w io.Writer) {

}

// Errors
var (
	ErrInvalidEncoding = errors.New("invalid binary encoding")
	ErrInvalidPeriod   = errors.New("invalid period")
	ErrInvalidDuration = errors.New("invalid duration")
)
<commit_msg>added text decoding<commit_after>package ics

import (
	"encoding/base64"
	"errors"
	"io"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/MJKWoolnough/parser"
)

type Binary []byte

func (b *Binary) Decode(params map[string]string, data string) error {
	if params["ENCODING"] != "BASE64" {
		return ErrInvalidEncoding
	}
	cb, err := base64.StdEncoding.DecodeString(data)
	*b = cb
	return err
}

func (b *Binary) Encode(w io.Writer) {
	e := base64.NewEncoder(base64.StdEncoding, w)
	e.Write([]byte(*b))
	e.Close()
}

type Boolean bool

func (b *Boolean) Decode(params map[string]string, data string) error {
	cb, err := strconv.ParseBool(data)
	*b = cb
	return err
}

var (
	booleanTrue  = [...]byte{'T', 'R', 'U', 'E'}
	booleanFalse = [...]byte{'F', 'A', 'L', 'S', 'E'}
)

func (b *Boolean) Encode(w io.Writer) {
	if *b {
		w.Write(booleanTrue[:])
	} else {
		w.Write(booleanFalse[:])
	}
}

type CalAddress struct {
	URI
}

type Date struct {
	time.Time
}

func (d *Date) Decode(params map[string]string, data string) error {
	t, err := time.Parse("20060102", data)
	if err != nil {
		return err
	}
	d.Time = t
	return nil
}

func (d *Date) Encode(w io.Writer) {
	b := make([]byte, 0, 8)
	w.Write([]byte(d.AppendFormat(b, "20060102")))
}

type DateTime struct {
	time.Time
}

func (d *DateTime) Decode(params map[string]string, data string) error {
	if tz, ok := params["TZID"]; ok {
		l, err := time.LoadLocation(tz)
		if err != nil {
			return err
		}
		t, err := time.ParseInLocation("20060102T150405", data, l)
		if err != nil {
			return err
		}
		d.Time = t
	} else if len(data) > 0 && data[len(data)-1] == 'Z' {
		t, err := time.ParseInLocation("20060102T150405Z", data, time.UTC)
		if err != nil {
			return err
		}
		d.Time = t
	} else {
		t, err := time.ParseInLocation("20060102T150405", data, time.Local)
		if err != nil {
			return err
		}
		d.Time = t
	}
	return nil
}

func (d *DateTime) Encode(w io.Writer) {
	b := make([]byte, 0, 16)
	switch d.Location() {
	case time.UTC:
		b = d.AppendFormat(b, "20060102T150405Z")
	case time.Local:
		b = d.AppendFormat(b, "20060102T150405")
	default:
		b = d.AppendFormat(b, "20060102T150405")
	}
	w.Write(b)
}

type Duration struct {
	Negative                             bool
	Weeks, Days, Hours, Minutes, Seconds uint
}

func (d *Duration) Decode(params map[string]string, data string) error {
	t := parser.NewStringTokeniser(data)
	var neg bool
	if t.Accept("-") {
		neg = true
	} else {
		t.Accept("+")
	}
	if !t.Accept("P") {
		return ErrInvalidDuration
	}
	var level uint8
	for t.Peek() != -1 {
		t.Get()
		mode := t.AcceptRun("0123456789")
		num, err := strconv.ParseUint(t.Get(), 10, 0)
		if err != nil {
			return err
		}
		switch mode {
		case 'W':
			t.Accept("W")
			if t.Peek() != -1 {
				return ErrInvalidDuration
			}
			d.Weeks = num
			return nil
		case 'D':
			if level > 0 {
				return ErrInvalidDuration
			}
			t.Accept("D")
			d.Days = num
			level = 1
		case 'H':
			if level > 1 {
				return ErrInvalidDuration
			}
			t.Accept("H")
			d.Hours = num
			level = 2
		case 'M':
			if level > 2 {
				return ErrInvalidDuration
			}
			t.Accept("M")
			d.Minutes = num
			level = 3
		case 'S':
			if level > 3 {
				return ErrInvalidDuration
			}
			t.Accept("S")
			if t.Peek() != -1 {
				return ErrInvalidDuration
			}
			d.Seconds = num
		default:
			return ErrInvalidDuration
		}
	}
	if level == 0 {
		return ErrInvalidDuration
	}
	return nil
}

func itoa(i uint) []byte {
	if i == 0 {
		return []byte{'0'}
	}
	var digits [20]byte
	pos := 20
	for ; n > 0; n /= 10 {
		pos--
		digits[pos] = '0' + byte(n%10)
	}
	return digits[pos:]
}

func (d *Duration) Encode(w io.Writer) {
	data := make([]byte, 0, 64)
	if d.Negative {
		data = append(data, '-')
	}
	data = append(data, 'P')
	if d.Weeks != 0 {
		data = append(data, itoa(d.Weeks)...)
		data = append(data, 'W')
		return nil
	} else {
		if d.Days != 0 {
			data = append(data, itoa(d.Days)...)
			data = append(data, 'D')
		}
		if d.Days == 0 || (d.Hours != 0 || d.Minutes != 0 || d.Seconds != 0) {
			data = append(data, 'T')
			if d.Hours != 0 {
				data = append(data, itoa(d.Hours)...)
				data = append(data, 'H')
				if d.Minutes != 0 || d.Seconds != 0 {
					data = append(data, itoa(d.Minutes)...)
					data = append(data, 'M')
					if d.Seconds != 0 {
						data = append(data, itoa(d.Seconds)...)
						data = append(data, 'S')
					}
				}
			} else if d.Minutes != 0 {
				data = append(data, itoa(d.Minutes)...)
				data = append(data, 'M')
				if d.Seconds != 0 {
					data = append(data, itoa(d.Seconds)...)
					data = append(data, 'S')
				}
			} else {
				data = append(data, itoa(d.Seconds)...)
				data = append(data, 'S')
			}
		}
	}
	w.Write(data)
}

type Float float64

func (f *Float) Decode(params map[string]string, data string) error {
	cf, err := strconv.ParseFloat(data, 64)
	if err != nil {
		return err
	}
	*f = Float(cf)
	return nil
}

func (f *Float) Encode(w io.Writer) {
	w.Write([]byte(strconv.FormatFloat(float64(*f), 'f', 64)))
}

type Integer int32

func (i *Integer) Decode(params map[string]string, data string) error {
	ci, err := strconv.ParseInt(data, 10, 32)
	if err != nil {
		return err
	}
	*i = Integer(ci)
	return nil
}

func (i *Integer) Encode(w io.Writer) {
	w.Write([]byte(strconv.FormatInt(int64(*i), 10)))
}

type Period struct {
	Start, End DateTime
	Duration   Duration
}

func (p *Period) Decode(params map[string]string, data string) error {
	i := strings.IndexByte(data, '/')
	if i == -1 || len(data) == i+1 {
		return ErrInvalidPeriod
	}
	err := p.Start.Decode(params, data[:i])
	if err != nil {
		return err
	}
	if data[i+1] == 'P' || data[i+1] == '+' {
		return p.Duration.Decode(params, data[i+1:])
	}
	return p.End.Decode(params, data[i+1:])
}

func (p *Period) Encode(w io.Writer) {
	p.Start.Encode(w)
	w.Write([]byte{'/'})
	if p.End.IsZero() {
		p.Duration.Encode(w)
	} else {
		p.End.Encode(w)
	}
}

type Recur struct {
}

func (r *Recur) Decode(params map[string]string, data string) error {
	return nil
}

func (r *Recur) Encode(w io.Writer) {

}

type Text string

func (t *Text) Decode(params map[string]string, data string) error {
	t := parser.NewStringTokeniser(data)
	d := make([]byte, 0, len(data))
Loop:
	for {
		c := t.ExceptRun("\";:\\,^")
		d = append(d, t.Get()...)
		switch c {
		case -1:
			break Loop
		case '\\':
			t.Accept("\\")
			switch t.Except("") {
			case '\\':
				d = append(d, '\\')
			case ';':
				d = append(d, ';')
			case ',':
				d = append(d, ',')
			case 'N', 'n':
				d = append(d, '\n')
			default:
				return ErrInvalidText
			}
		case '^':
			t.Accept("^")
			switch c := t.Except(""); c {
			case 'n':
				d = append(d, '\n')
			case '^':
				d = append(d, '^')
			case '\'':
				d = append(d, '"')
			default:
				d = append(d, '^', c)
			}
		default:
			return ErrInvalidText
		}
	}
	*t = Text(d)
	return nil
}

func (t *Text) Encode(w io.Writer) {

}

type Time struct {
	time.Time
}

func (t *Time) Decode(params map[string]string, data string) error {
	return nil
}

func (t *Time) Encode(w io.Writer) {

}

type URI struct {
	url.URL
}

func (u *URI) Decode(params map[string]string, data string) error {
	cu, err := url.Parse(data)
	if err != nil {
		return err
	}
	u.URL = cu
	return nil
}

func (u *URI) Encode(w io.Writer) {
	w.Write([]byte(u.URL.String()))
}

type UTCOffset int

func (u *UTCOffset) Decode(params map[string]string, data string) error {
	return nil
}

func (u *UTCOffset) Encode(w io.Writer) {

}

// Errors
var (
	ErrInvalidEncoding = errors.New("invalid binary encoding")
	ErrInvalidPeriod   = errors.New("invalid period")
	ErrInvalidDuration = errors.New("invalid duration")
	ErrInvalidText     = errors.New("invalid encoded text")
)
<|endoftext|>


<commit_before>package dig

import "reflect"

var (
	_noValue          reflect.Value
	_errType          = reflect.TypeOf((*error)(nil)).Elem()
	_inInterfaceType  = reflect.TypeOf((*digInObject)(nil)).Elem()
	_outInterfaceType = reflect.TypeOf((*digOutObject)(nil)).Elem()
	_inType           = reflect.TypeOf(In{})
)

// In is an embeddable object that signals to dig that the struct
// should be treated differently. Instead of itself becoming an object
// in the graph, memebers of the struct are inserted into the graph.
//
// Tags on those memebers control their behavior. For example,
//
//    type Input struct {
//      dig.In
//
//      S *Something
//      T *Thingy `optional:"true"`
//    }
//
type In struct{}

// Out is an embeddable type that signals to dig that the returned
// struct should be treated differently. Instead of the struct itself
// becoming part of the container, all members of the struct will.
type Out struct{}

// TODO: better usage docs
// Try to add some symmetry for In-Out docs as well.

// In is the only instance that implements the digInObject interface.
func (In) digInObject() {}

// Out is the only instance that implements the digOutObject interface
func (Out) digOutObject() {}

// Users embed the In struct to opt a struct in as a parameter object.
// This provides us an easy way to check if something embeds dig.In
// without iterating through all its fields.
type digInObject interface {
	digInObject()
}

type digOutObject interface {
	digOutObject()
}

func isInObject(t reflect.Type) bool {
	return t.Implements(_inInterfaceType) && t.Kind() == reflect.Struct
}

func isOutObject(t reflect.Type) bool {
	return t.Implements(_outInterfaceType) && t.Kind() == reflect.Struct
}

// Validate interfaces are satisfied
var (
	_ digInObject  = In{}
	_ digOutObject = Out{}
)
<commit_msg>Remove unused variable (#97)<commit_after>package dig

import "reflect"

var (
	_noValue          reflect.Value
	_errType          = reflect.TypeOf((*error)(nil)).Elem()
	_inInterfaceType  = reflect.TypeOf((*digInObject)(nil)).Elem()
	_outInterfaceType = reflect.TypeOf((*digOutObject)(nil)).Elem()
)

// In is an embeddable object that signals to dig that the struct
// should be treated differently. Instead of itself becoming an object
// in the graph, memebers of the struct are inserted into the graph.
//
// Tags on those memebers control their behavior. For example,
//
//    type Input struct {
//      dig.In
//
//      S *Something
//      T *Thingy `optional:"true"`
//    }
//
type In struct{}

// Out is an embeddable type that signals to dig that the returned
// struct should be treated differently. Instead of the struct itself
// becoming part of the container, all members of the struct will.
type Out struct{}

// TODO: better usage docs
// Try to add some symmetry for In-Out docs as well.

// In is the only instance that implements the digInObject interface.
func (In) digInObject() {}

// Out is the only instance that implements the digOutObject interface
func (Out) digOutObject() {}

// Users embed the In struct to opt a struct in as a parameter object.
// This provides us an easy way to check if something embeds dig.In
// without iterating through all its fields.
type digInObject interface {
	digInObject()
}

type digOutObject interface {
	digOutObject()
}

func isInObject(t reflect.Type) bool {
	return t.Implements(_inInterfaceType) && t.Kind() == reflect.Struct
}

func isOutObject(t reflect.Type) bool {
	return t.Implements(_outInterfaceType) && t.Kind() == reflect.Struct
}

// Validate interfaces are satisfied
var (
	_ digInObject  = In{}
	_ digOutObject = Out{}
)
<|endoftext|>


<commit_before>package certcenter

import (
	"fmt"
	"net/http"
	"time"
)

var Bearer string

const (
	// Param type is QueryString (eg. ?CertCenterOrderId=123)
	CC_PARAM_TYPE_QS = 1 << iota
	// Param type is Path (eg. /:CertCenterOrderId/)
	CC_PARAM_TYPE_PATH
	// Param type is Body (JSON POST)
	CC_PARAM_TYPE_BODY
)

func checkErr(err error) {
	if err != nil {
		fmt.Println(err)
	}
}

// Represents an API request
type apiRequest struct {
	method     string
	httpMethod string
	url        string
	result     interface{}
	request    interface{}
	client     *http.Client
	statusCode int
}

// ProfileResult represents a GET /Profile response
type ProfileResult struct {
	AuthType        string
	AuthorizationID int64
	Country         string
	Currency        string
	CustomerID      int64
	Locale          string
	OAuth2_Token    string
	Scope           string
	Timezone        string
}

// LimitResult represents a GET /Limit response
type LimitResult struct {
	Success   bool `json:"success"`
	LimitInfo struct {
		Limit float64
		Used  float64
	}
}

// ProductsResult represents a GET /Products response
type ProductsResult struct {
	Success  bool `json:"success"`
	Products []string
}

// ProductDetailsResult represents a GET /ProductDetails response
type ProductDetailsResult struct {
	Success        bool `json:"success"`
	ProductDetails struct {
		CA                string
		Currency          string
		Features          []string
		Licenses          int
		MaxValidityPeriod int
		Price             float64
		ProductCode       string
		ProductName       string
		RefundPeriod      int
		RenewPeriod       int
		SANFeatures       []string
		SANHostPrice      float64
		SANMaxHosts       int
		SANPackagePrice   float64
		SANPackageSize    int
	}
}

// ProductDetailsRequest represents a GET /ProductDetails request
type ProductDetailsRequest struct {
	ProductCode string
}

// QuoteResult represents a GET /Quote response
type QuoteResult struct {
	Success         bool `json:"success"`
	Currency        string
	OrderParameters struct {
		ProductCode         string
		ServerCount         int
		SubjectAltNameCount int
		ValidityPeriod      int
	}
	Price float64
}

// QuoteRequest represents a GET /Quote request
type QuoteRequest struct {
	ProductCode         string
	SubjectAltNameCount int
	ValidityPeriod      int
	ServerCount         int
}

// ValidateCSRResult represents a POST /ValidateCSR response
type ValidateCSRResult struct {
	Success   bool `json:"success"`
	ParsedCSR struct {
		CommonName             string
		Organization           string
		OrganizationUnit       string
		Email                  string
		State                  string
		Locality               string
		Country                string
		KeyLength              int
		SignaturAlgorithm      string
		KeyEncryptionAlgorithm string
	}
}

// ValidateCSRRequest represents a POST /ValidateCSR request
type ValidateCSRRequest struct {
	CSR string // PEM-encoded PKCS#10
}

// UserAgreementRequest represents a GET /ProductDetails response
type UserAgreementRequest struct {
	ProductCode string
}

// UserAgreementResult represents a GET /ProductDetails request
type UserAgreementResult struct {
	Success       bool `json:"success"`
	ProductCode   string
	UserAgreement string
}

// ApproverListRequest represents a GET /ApproverList response
type ApproverListRequest struct {
	CommonName  string
	ProductCode string
}

// ApproverListResult represents a GET /ApproverList request
type ApproverListResult struct {
	Success      bool `json:"success"`
	ApproverList []struct {
		ApproverEmail string
		ApproverType  string // Domain, Generic
	}
}

// OrderResult represents a POST /Order response
type OrderResult struct {
	Success           bool `json:"success"`
	Timestamp         time.Time
	CertCenterOrderID int
	OrderParameters   struct {
		CSR                    string // PEM-encoded PKCS#10
		IsCompetitiveUpgrade   bool
		IsRenewal              bool
		PartnerOrderID         string
		ProductCode            string
		ServerCount            int
		SignatureHashAlgorithm string
		SubjectAltNameCount    int
		SubjectAltNames        []string
		ValidityPeriod         int // 12 or 24 month (days for AlwaysOnSSL, min. 180, max. 365)
		// AlwaysOnSSL (Symantec Encryption Everywhere) only:
		DVAuthMethod string // DNS, EMAIL

	}
	// AlwaysOnSSL (Symantec Encryption Everywhere) only:
	Fulfillment struct {
		Certificate       string
		Certificate_PKCS7 string
		Intermediate      string
	}
}

// OrderParameters represents generic Order Parameters
type OrderParameters struct {
	CSR                    string   // PEM-encoded PKCS#10
	IsCompetitiveUpgrade   bool     `json:",omitempty"`
	IsRenewal              bool     `json:",omitempty"`
	PartnerOrderID         string   `json:",omitempty"`
	ProductCode            string   `json:",omitempty"`
	ServerCount            int      `json:",omitempty"`
	SignatureHashAlgorithm string   `json:",omitempty"`
	SubjectAltNameCount    int      `json:",omitempty"`
	SubjectAltNames        []string `json:",omitempty"`
	ValidityPeriod         int      `json:",omitempty"` // 12 or 24 month (days for AlwaysOnSSL, min. 180, max. 365)
	// AlwaysOnSSL (Symantec Encryption Everywhere) only:
	DVAuthMethod  string `json:",omitempty"` // DNS, EMAIL
	ApproverEmail string `json:",omitempty"`
}

// Contact represents a generic Contact type (for AdminContact and TechContact)
type Contact struct {
	Title               string              `json:",omitempty"`
	FirstName           string              `json:",omitempty"`
	LastName            string              `json:",omitempty"`
	OrganizationName    string              `json:",omitempty"`
	OrganizationAddress OrganizationAddress `json:",omitempty"`
	Phone               string              `json:",omitempty"`
	Fax                 string              `json:",omitempty"`
	Email               string              `json:",omitempty"`
}

// OrganizationAddress holds general information about a organization
type OrganizationAddress struct {
	AddressLine1 string `json:",omitempty"`
	PostalCode   string `json:",omitempty"`
	City         string `json:",omitempty"`
	Region       string `json:",omitempty"`
	Country      string `json:",omitempty"`
	Phone        string `json:",omitempty"`
	Fax          string `json:",omitempty"`
}

// OrderRequest represents a POST /Order request
type OrderRequest struct {
	OrganizationInfo struct {
		OrganizationName    string              `json:",omitempty"`
		OrganizationAddress OrganizationAddress `json:",omitempty"`
	} `json:",omitempty"`
	OrderParameters OrderParameters `json:",omitempty"`
	AdminContact    Contact         `json:",omitempty"`
	TechContact     Contact         `json:",omitempty"`
}
<commit_msg>Few changes<commit_after>package certcenter

import (
	"fmt"
	"net/http"
	"time"
)

// Bearer represents the authentication token you're going to use
var Bearer string

const (
	// CC_PARAM_TYPE_QS is QueryString (eg. ?CertCenterOrderId=123)
	CC_PARAM_TYPE_QS = 1 << iota
	// CC_PARAM_TYPE_PATH is Path (eg. /:CertCenterOrderId/)
	CC_PARAM_TYPE_PATH
	// CC_PARAM_TYPE_BODY is Body (JSON POST)
	CC_PARAM_TYPE_BODY
)

func checkErr(err error) {
	if err != nil {
		fmt.Println(err)
	}
}

// Represents an API request
type apiRequest struct {
	method     string
	httpMethod string
	url        string
	result     interface{}
	request    interface{}
	client     *http.Client
	statusCode int
}

// ProfileResult represents a GET /Profile response
type ProfileResult struct {
	AuthType        string
	AuthorizationID int64
	Country         string
	Currency        string
	CustomerID      int64
	Locale          string
	OAuth2Token     string `json:"OAuth2Token"`
	Scope           string
	Timezone        string
}

// LimitResult represents a GET /Limit response
type LimitResult struct {
	Success   bool `json:"success"`
	LimitInfo struct {
		Limit float64
		Used  float64
	}
}

// ProductsResult represents a GET /Products response
type ProductsResult struct {
	Success  bool `json:"success"`
	Products []string
}

// ProductDetailsResult represents a GET /ProductDetails response
type ProductDetailsResult struct {
	Success        bool `json:"success"`
	ProductDetails struct {
		CA                string
		Currency          string
		Features          []string
		Licenses          int
		MaxValidityPeriod int
		Price             float64
		ProductCode       string
		ProductName       string
		RefundPeriod      int
		RenewPeriod       int
		SANFeatures       []string
		SANHostPrice      float64
		SANMaxHosts       int
		SANPackagePrice   float64
		SANPackageSize    int
	}
}

// ProductDetailsRequest represents a GET /ProductDetails request
type ProductDetailsRequest struct {
	ProductCode string
}

// QuoteResult represents a GET /Quote response
type QuoteResult struct {
	Success         bool `json:"success"`
	Currency        string
	OrderParameters struct {
		ProductCode         string
		ServerCount         int
		SubjectAltNameCount int
		ValidityPeriod      int
	}
	Price float64
}

// QuoteRequest represents a GET /Quote request
type QuoteRequest struct {
	ProductCode         string
	SubjectAltNameCount int
	ValidityPeriod      int
	ServerCount         int
}

// ValidateCSRResult represents a POST /ValidateCSR response
type ValidateCSRResult struct {
	Success   bool `json:"success"`
	ParsedCSR struct {
		CommonName             string
		Organization           string
		OrganizationUnit       string
		Email                  string
		State                  string
		Locality               string
		Country                string
		KeyLength              int
		SignaturAlgorithm      string
		KeyEncryptionAlgorithm string
	}
}

// ValidateCSRRequest represents a POST /ValidateCSR request
type ValidateCSRRequest struct {
	CSR string // PEM-encoded PKCS#10
}

// UserAgreementRequest represents a GET /ProductDetails response
type UserAgreementRequest struct {
	ProductCode string
}

// UserAgreementResult represents a GET /ProductDetails request
type UserAgreementResult struct {
	Success       bool `json:"success"`
	ProductCode   string
	UserAgreement string
}

// ApproverListRequest represents a GET /ApproverList response
type ApproverListRequest struct {
	CommonName  string
	ProductCode string
}

// ApproverListResult represents a GET /ApproverList request
type ApproverListResult struct {
	Success      bool `json:"success"`
	ApproverList []struct {
		ApproverEmail string
		ApproverType  string // Domain, Generic
	}
}

// OrderResult represents a POST /Order response
type OrderResult struct {
	Success           bool `json:"success"`
	Timestamp         time.Time
	CertCenterOrderID int
	OrderParameters   struct {
		CSR                    string // PEM-encoded PKCS#10
		IsCompetitiveUpgrade   bool
		IsRenewal              bool
		PartnerOrderID         string
		ProductCode            string
		ServerCount            int
		SignatureHashAlgorithm string
		SubjectAltNameCount    int
		SubjectAltNames        []string
		ValidityPeriod         int // 12 or 24 month (days for AlwaysOnSSL, min. 180, max. 365)
		// AlwaysOnSSL (Symantec Encryption Everywhere) only:
		DVAuthMethod string // DNS, EMAIL

	}
	// AlwaysOnSSL (Symantec Encryption Everywhere) only:
	Fulfillment struct {
		Certificate       string
		Certificate_PKCS7 string
		Intermediate      string
	}
}

// OrderParameters represents generic Order Parameters
type OrderParameters struct {
	CSR                    string   // PEM-encoded PKCS#10
	IsCompetitiveUpgrade   bool     `json:",omitempty"`
	IsRenewal              bool     `json:",omitempty"`
	PartnerOrderID         string   `json:",omitempty"`
	ProductCode            string   `json:",omitempty"`
	ServerCount            int      `json:",omitempty"`
	SignatureHashAlgorithm string   `json:",omitempty"`
	SubjectAltNameCount    int      `json:",omitempty"`
	SubjectAltNames        []string `json:",omitempty"`
	ValidityPeriod         int      `json:",omitempty"` // 12 or 24 month (days for AlwaysOnSSL, min. 180, max. 365)
	// AlwaysOnSSL (Symantec Encryption Everywhere) only:
	DVAuthMethod  string `json:",omitempty"` // DNS, EMAIL
	ApproverEmail string `json:",omitempty"`
}

// Contact represents a generic Contact type (for AdminContact and TechContact)
type Contact struct {
	Title               string              `json:",omitempty"`
	FirstName           string              `json:",omitempty"`
	LastName            string              `json:",omitempty"`
	OrganizationName    string              `json:",omitempty"`
	OrganizationAddress OrganizationAddress `json:",omitempty"`
	Phone               string              `json:",omitempty"`
	Fax                 string              `json:",omitempty"`
	Email               string              `json:",omitempty"`
}

// OrganizationAddress holds general information about a organization
type OrganizationAddress struct {
	AddressLine1 string `json:",omitempty"`
	PostalCode   string `json:",omitempty"`
	City         string `json:",omitempty"`
	Region       string `json:",omitempty"`
	Country      string `json:",omitempty"`
	Phone        string `json:",omitempty"`
	Fax          string `json:",omitempty"`
}

// OrderRequest represents a POST /Order request
type OrderRequest struct {
	OrganizationInfo struct {
		OrganizationName    string              `json:",omitempty"`
		OrganizationAddress OrganizationAddress `json:",omitempty"`
	} `json:",omitempty"`
	OrderParameters OrderParameters `json:",omitempty"`
	AdminContact    Contact         `json:",omitempty"`
	TechContact     Contact         `json:",omitempty"`
}
<|endoftext|>


<commit_before>package dockerclient

type ContainerConfig struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int
	MemorySwap      int
	CpuShares       int
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	Tty             bool
	OpenStdin       bool
	StdinOnce       bool
	Env             []string
	Cmd             []string
	Image           string
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
}

type HostConfig struct {
	Binds           []string
	ContainerIDFile string
	LxcConf         []map[string]string
	Privileged      bool
	PortBindings    map[string][]PortBinding
	Links           []string
	PublishAllPorts bool
	Dns             []string
	DnsSearch       []string
	VolumesFrom     []string
}

type PortBinding struct {
	HostIp   string
	HostPort string
}

type ContainerInfo struct {
	Id     string
	Create string
	Path   string
	Name   string
	Args   []string
	Config *ContainerConfig
	State  struct {
		Running   bool
		Pid       int
		ExitCode  int
		StartedAt string
		Ghost     bool
	}
	Image           string
	NetworkSettings struct {
		IpAddress   string
		IpPrefixLen int
		Gateway     string
		Bridge      string
		Ports       map[string][]PortBinding
	}
	SysInitPath    string
	ResolvConfPath string
	Volumes        map[string]string
	HostConfig     *HostConfig
}

type Port struct {
	PrivatePort int
	PublicPort  int
	Type        string
}

type Container struct {
	Id         string
	Names      []string
	Image      string
	Command    string
	Created    int
	Status     string
	Ports      []Port
	SizeRw     int
	SizeRootFs int
}

type Event struct {
	Id     string
	Status string
	From   string
	Time   int
}

type Version struct {
	Version   string
	GitCommit string
	GoVersion string
}

type RespContainersCreate struct {
	Id       string
	Warnings []string
}
<commit_msg>types: fix Create to Created<commit_after>package dockerclient

type ContainerConfig struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int
	MemorySwap      int
	CpuShares       int
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	Tty             bool
	OpenStdin       bool
	StdinOnce       bool
	Env             []string
	Cmd             []string
	Image           string
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
}

type HostConfig struct {
	Binds           []string
	ContainerIDFile string
	LxcConf         []map[string]string
	Privileged      bool
	PortBindings    map[string][]PortBinding
	Links           []string
	PublishAllPorts bool
	Dns             []string
	DnsSearch       []string
	VolumesFrom     []string
}

type PortBinding struct {
	HostIp   string
	HostPort string
}

type ContainerInfo struct {
	Id     string
	Created string
	Path   string
	Name   string
	Args   []string
	Config *ContainerConfig
	State  struct {
		Running   bool
		Pid       int
		ExitCode  int
		StartedAt string
		Ghost     bool
	}
	Image           string
	NetworkSettings struct {
		IpAddress   string
		IpPrefixLen int
		Gateway     string
		Bridge      string
		Ports       map[string][]PortBinding
	}
	SysInitPath    string
	ResolvConfPath string
	Volumes        map[string]string
	HostConfig     *HostConfig
}

type Port struct {
	PrivatePort int
	PublicPort  int
	Type        string
}

type Container struct {
	Id         string
	Names      []string
	Image      string
	Command    string
	Created    int
	Status     string
	Ports      []Port
	SizeRw     int
	SizeRootFs int
}

type Event struct {
	Id     string
	Status string
	From   string
	Time   int
}

type Version struct {
	Version   string
	GitCommit string
	GoVersion string
}

type RespContainersCreate struct {
	Id       string
	Warnings []string
}
<|endoftext|>


<commit_before>package venom

import "encoding/xml"

const (
	// DetailsLow prints only summary results
	DetailsLow = "low"
	// DetailsMedium prints progress bar and summary
	DetailsMedium = "medium"
	// DetailsHigh prints progress bar and details
	DetailsHigh = "high"
)

// Aliases contains list of aliases
type Aliases map[string]string

// ExecutorResult represents an executor result on a test step
type ExecutorResult map[string]interface{}

// StepAssertions contains step assertions
type StepAssertions struct {
	Assertions []string `json:"assertions,omitempty" yaml:"assertions,omitempty"`
}

// StepExtracts contains "step extracts"
type StepExtracts struct {
	Extracts map[string]string `json:"extracts,omitempty" yaml:"extracts,omitempty"`
}

// Executor execute a testStep.
type Executor interface {
	// Run run a Test Step
	Run(TestCaseContext, Logger, TestStep) (ExecutorResult, error)
}

// TestCaseContext represents the context of a testcase
type TestCaseContext interface {
	Init() error
	Close() error
	SetTestCase(tc TestCase)
	GetName() string
}

// CommonTestCaseContext represents a Default TestCase Context
type CommonTestCaseContext struct {
	TestCaseContext
	TestCase TestCase
	Name     string
}

// SetTestCase set testcase in context
func (tcc *CommonTestCaseContext) SetTestCase(tc TestCase) {
	tcc.TestCase = tc
}

// GetName Get the context name
func (tcc *CommonTestCaseContext) GetName() string {
	return tcc.Name
}

// ExecutorWrap contains an executor implementation and some attributes
type ExecutorWrap struct {
	executor Executor
	retry    int // nb retry a test case if it is in failure.
	delay    int // delay between two retries
	timeout  int // timeout on executor
}

// executorWithDefaultAssertions execute a testStep.
type executorWithDefaultAssertions interface {
	// GetDefaultAssertion returns default assertions
	GetDefaultAssertions() *StepAssertions
}

type executorWithZeroValueResult interface {
	ZeroValueResult() ExecutorResult
}

// Tests contains all informations about tests in a pipeline build
type Tests struct {
	XMLName      xml.Name    `xml:"testsuites" json:"-" yaml:"-"`
	Total        int         `xml:"-" json:"total"`
	TotalOK      int         `xml:"-" json:"ok"`
	TotalKO      int         `xml:"-" json:"ko"`
	TotalSkipped int         `xml:"-" json:"skipped"`
	TestSuites   []TestSuite `xml:"testsuite" json:"test_suites"`
}

// TestSuite is a single JUnit test suite which may contain many
// testcases.
type TestSuite struct {
	XMLName    xml.Name               `xml:"testsuite" json:"-" yaml:"-"`
	Disabled   int                    `xml:"disabled,attr,omitempty" json:"disabled" yaml:"-"`
	Errors     int                    `xml:"errors,attr,omitempty" json:"errors" yaml:"-"`
	Failures   int                    `xml:"failures,attr,omitempty" json:"failures" yaml:"-"`
	Hostname   string                 `xml:"hostname,attr,omitempty" json:"hostname" yaml:"-"`
	ID         string                 `xml:"id,attr,omitempty" json:"id" yaml:"-"`
	Name       string                 `xml:"name,attr" json:"name" yaml:"name"`
	Package    string                 `xml:"package,attr,omitempty" json:"package" yaml:"-"`
	Properties []Property             `xml:"-" json:"properties" yaml:"-"`
	Skipped    int                    `xml:"skipped,attr,omitempty" json:"skipped" yaml:"skipped,omitempty"`
	Total      int                    `xml:"tests,attr" json:"total" yaml:"total,omitempty"`
	TestCases  []TestCase             `xml:"testcase" hcl:"testcase" json:"tests" yaml:"testcases"`
	Time       string                 `xml:"time,attr,omitempty" json:"time" yaml:"-"`
	Timestamp  string                 `xml:"timestamp,attr,omitempty" json:"timestamp" yaml:"-"`
	Vars       map[string]interface{} `xml:"-" json:"-" yaml:"vars"`
	Templater  *Templater             `xml:"-" json:"-" yaml:"-"`
}

// Property represents a key/value pair used to define properties.
type Property struct {
	XMLName xml.Name `xml:"property" json:"-" yaml:"-"`
	Name    string   `xml:"name,attr" json:"name" yaml:"-"`
	Value   string   `xml:"value,attr" json:"value" yaml:"-"`
}

// TestCase is a single test case with its result.
type TestCase struct {
	XMLName    xml.Name               `xml:"testcase" json:"-" yaml:"-"`
	Assertions []string               `xml:"assertions,attr,omitempty" json:"assertions" yaml:"-"`
	Classname  string                 `xml:"classname,attr,omitempty" json:"classname" yaml:"-"`
	Errors     []Failure              `xml:"error,omitempty" json:"errors" yaml:"errors,omitempty"`
	Failures   []Failure              `xml:"failure,omitempty" json:"failures" yaml:"failures,omitempty"`
	Name       string                 `xml:"name,attr" json:"name" yaml:"name"`
	Skipped    []Skipped              `xml:"skipped,omitempty" json:"skipped" yaml:"skipped,omitempty"`
	Status     string                 `xml:"status,attr,omitempty" json:"status" yaml:"status,omitempty"`
	Systemout  InnerResult            `xml:"system-out,omitempty" json:"systemout" yaml:"systemout,omitempty"`
	Systemerr  InnerResult            `xml:"system-err,omitempty" json:"systemerr" yaml:"systemerr,omitempty"`
	Time       string                 `xml:"time,attr,omitempty" json:"time" yaml:"time,omitempty"`
	TestSteps  []TestStep             `xml:"-" hcl:"step" json:"steps" yaml:"steps"`
	Context    map[string]interface{} `xml:"-" json:"-" yaml:"context,omitempty"`
}

// TestStep represents a testStep
type TestStep map[string]interface{}

// Failure contains data related to a failed test.
type Skipped struct {
	Value string `xml:",cdata" json:"value" yaml:"value,omitempty"`
}
type Failure struct {
	Value   string `xml:",cdata" json:"value" yaml:"value,omitempty"`
	Type    string `xml:"type,attr,omitempty" json:"type" yaml:"type,omitempty"`
	Message string `xml:"message,attr,omitempty" json:"message" yaml:"message,omitempty"`
}

// InnerResult is used by TestCase
type InnerResult struct {
	Value string `xml:",cdata" json:"value" yaml:"value"`
}

//Logger is basically an interface for logrus.Entry
type Logger interface {
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Warningf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})
}
<commit_msg>refactor: remove unused Assertions on TestCase<commit_after>package venom

import "encoding/xml"

const (
	// DetailsLow prints only summary results
	DetailsLow = "low"
	// DetailsMedium prints progress bar and summary
	DetailsMedium = "medium"
	// DetailsHigh prints progress bar and details
	DetailsHigh = "high"
)

// Aliases contains list of aliases
type Aliases map[string]string

// ExecutorResult represents an executor result on a test step
type ExecutorResult map[string]interface{}

// StepAssertions contains step assertions
type StepAssertions struct {
	Assertions []string `json:"assertions,omitempty" yaml:"assertions,omitempty"`
}

// StepExtracts contains "step extracts"
type StepExtracts struct {
	Extracts map[string]string `json:"extracts,omitempty" yaml:"extracts,omitempty"`
}

// Executor execute a testStep.
type Executor interface {
	// Run run a Test Step
	Run(TestCaseContext, Logger, TestStep) (ExecutorResult, error)
}

// TestCaseContext represents the context of a testcase
type TestCaseContext interface {
	Init() error
	Close() error
	SetTestCase(tc TestCase)
	GetName() string
}

// CommonTestCaseContext represents a Default TestCase Context
type CommonTestCaseContext struct {
	TestCaseContext
	TestCase TestCase
	Name     string
}

// SetTestCase set testcase in context
func (tcc *CommonTestCaseContext) SetTestCase(tc TestCase) {
	tcc.TestCase = tc
}

// GetName Get the context name
func (tcc *CommonTestCaseContext) GetName() string {
	return tcc.Name
}

// ExecutorWrap contains an executor implementation and some attributes
type ExecutorWrap struct {
	executor Executor
	retry    int // nb retry a test case if it is in failure.
	delay    int // delay between two retries
	timeout  int // timeout on executor
}

// executorWithDefaultAssertions execute a testStep.
type executorWithDefaultAssertions interface {
	// GetDefaultAssertion returns default assertions
	GetDefaultAssertions() *StepAssertions
}

type executorWithZeroValueResult interface {
	ZeroValueResult() ExecutorResult
}

// Tests contains all informations about tests in a pipeline build
type Tests struct {
	XMLName      xml.Name    `xml:"testsuites" json:"-" yaml:"-"`
	Total        int         `xml:"-" json:"total"`
	TotalOK      int         `xml:"-" json:"ok"`
	TotalKO      int         `xml:"-" json:"ko"`
	TotalSkipped int         `xml:"-" json:"skipped"`
	TestSuites   []TestSuite `xml:"testsuite" json:"test_suites"`
}

// TestSuite is a single JUnit test suite which may contain many
// testcases.
type TestSuite struct {
	XMLName    xml.Name               `xml:"testsuite" json:"-" yaml:"-"`
	Disabled   int                    `xml:"disabled,attr,omitempty" json:"disabled" yaml:"-"`
	Errors     int                    `xml:"errors,attr,omitempty" json:"errors" yaml:"-"`
	Failures   int                    `xml:"failures,attr,omitempty" json:"failures" yaml:"-"`
	Hostname   string                 `xml:"hostname,attr,omitempty" json:"hostname" yaml:"-"`
	ID         string                 `xml:"id,attr,omitempty" json:"id" yaml:"-"`
	Name       string                 `xml:"name,attr" json:"name" yaml:"name"`
	Package    string                 `xml:"package,attr,omitempty" json:"package" yaml:"-"`
	Properties []Property             `xml:"-" json:"properties" yaml:"-"`
	Skipped    int                    `xml:"skipped,attr,omitempty" json:"skipped" yaml:"skipped,omitempty"`
	Total      int                    `xml:"tests,attr" json:"total" yaml:"total,omitempty"`
	TestCases  []TestCase             `xml:"testcase" hcl:"testcase" json:"tests" yaml:"testcases"`
	Time       string                 `xml:"time,attr,omitempty" json:"time" yaml:"-"`
	Timestamp  string                 `xml:"timestamp,attr,omitempty" json:"timestamp" yaml:"-"`
	Vars       map[string]interface{} `xml:"-" json:"-" yaml:"vars"`
	Templater  *Templater             `xml:"-" json:"-" yaml:"-"`
}

// Property represents a key/value pair used to define properties.
type Property struct {
	XMLName xml.Name `xml:"property" json:"-" yaml:"-"`
	Name    string   `xml:"name,attr" json:"name" yaml:"-"`
	Value   string   `xml:"value,attr" json:"value" yaml:"-"`
}

// TestCase is a single test case with its result.
type TestCase struct {
	XMLName   xml.Name               `xml:"testcase" json:"-" yaml:"-"`
	Classname string                 `xml:"classname,attr,omitempty" json:"classname" yaml:"-"`
	Errors    []Failure              `xml:"error,omitempty" json:"errors" yaml:"errors,omitempty"`
	Failures  []Failure              `xml:"failure,omitempty" json:"failures" yaml:"failures,omitempty"`
	Name      string                 `xml:"name,attr" json:"name" yaml:"name"`
	Skipped   []Skipped              `xml:"skipped,omitempty" json:"skipped" yaml:"skipped,omitempty"`
	Status    string                 `xml:"status,attr,omitempty" json:"status" yaml:"status,omitempty"`
	Systemout InnerResult            `xml:"system-out,omitempty" json:"systemout" yaml:"systemout,omitempty"`
	Systemerr InnerResult            `xml:"system-err,omitempty" json:"systemerr" yaml:"systemerr,omitempty"`
	Time      string                 `xml:"time,attr,omitempty" json:"time" yaml:"time,omitempty"`
	TestSteps []TestStep             `xml:"-" hcl:"step" json:"steps" yaml:"steps"`
	Context   map[string]interface{} `xml:"-" json:"-" yaml:"context,omitempty"`
}

// TestStep represents a testStep
type TestStep map[string]interface{}

// Skipped contains data related to a skipped test.
type Skipped struct {
	Value string `xml:",cdata" json:"value" yaml:"value,omitempty"`
}

// Failure contains data related to a failed test.
type Failure struct {
	Value   string `xml:",cdata" json:"value" yaml:"value,omitempty"`
	Type    string `xml:"type,attr,omitempty" json:"type" yaml:"type,omitempty"`
	Message string `xml:"message,attr,omitempty" json:"message" yaml:"message,omitempty"`
}

// InnerResult is used by TestCase
type InnerResult struct {
	Value string `xml:",cdata" json:"value" yaml:"value"`
}

//Logger is basically an interface for logrus.Entry
type Logger interface {
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Warningf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})
}
<|endoftext|>


<commit_before>package govalidator

import "reflect"

// Validator is a wrapper for validator functions, that returns bool and accepts string.
type Validator func(str string) bool
type tagOptions []string

// UnsupportedTypeError is a wrapper for reflect.Type
type UnsupportedTypeError struct {
	Type reflect.Type
}

// stringValues is a slice of reflect.Value holding *reflect.StringValue.
// It implements the methods to sort by string.
type stringValues []reflect.Value

// TagMap is a map of functions, that can be used as tags for ValidateStruct function.
var TagMap = map[string]Validator{
	"email":         IsEmail,
	"url":           IsURL,
	"alpha":         IsAlpha,
	"alphanum":      IsAlphanumeric,
	"numeric":       IsNumeric,
	"hexadecimal":   IsHexadecimal,
	"hexcolor":      IsHexcolor,
	"rgbcolor":      IsRGBcolor,
	"lowercase":     IsLowerCase,
	"uppercase":     IsUpperCase,
	"int":           IsInt,
	"float":         IsFloat,
	"null":          IsNull,
	"uuid":          IsUUID,
	"uuidv3":        IsUUIDv3,
	"uuidv4":        IsUUIDv4,
	"uuidv5":        IsUUIDv5,
	"creditcard":    IsCreditCard,
	"isbn10":        IsISBN10,
	"isbn13":        IsISBN13,
	"json":          IsJSON,
	"multibyte":     IsMultibyte,
	"ascii":         IsASCII,
	"fullwidth":     IsFullWidth,
	"halfwidth":     IsHalfWidth,
	"variablewidth": IsVariableWidth,
	"base64":        IsBase64,
	"datauri":       IsDataURI,
	"ipv4":          IsIPv4,
	"ipv6":          IsIPv6,
	"mac":           IsMAC,
	"latitude":      IsLatitude,
	"longitude":     IsLongitude,
}
<commit_msg>added unicode tags for struct validation<commit_after>package govalidator

import "reflect"

// Validator is a wrapper for validator functions, that returns bool and accepts string.
type Validator func(str string) bool
type tagOptions []string

// UnsupportedTypeError is a wrapper for reflect.Type
type UnsupportedTypeError struct {
	Type reflect.Type
}

// stringValues is a slice of reflect.Value holding *reflect.StringValue.
// It implements the methods to sort by string.
type stringValues []reflect.Value

// TagMap is a map of functions, that can be used as tags for ValidateStruct function.
var TagMap = map[string]Validator{
	"email":           IsEmail,
	"url":             IsURL,
	"alpha":           IsAlpha,
	"unicodeletter":   IsUnicodeLetter,
	"alphanum":        IsAlphanumeric,
	"unicodealphanum": IsUnicodeLetterNumeric,
	"numeric":         IsNumeric,
	"unicodenumeric":  IsUnicodeNumeric,
	"unicodedigit":    IsUnicodeDigit,
	"hexadecimal":     IsHexadecimal,
	"hexcolor":        IsHexcolor,
	"rgbcolor":        IsRGBcolor,
	"lowercase":       IsLowerCase,
	"uppercase":       IsUpperCase,
	"int":             IsInt,
	"float":           IsFloat,
	"null":            IsNull,
	"uuid":            IsUUID,
	"uuidv3":          IsUUIDv3,
	"uuidv4":          IsUUIDv4,
	"uuidv5":          IsUUIDv5,
	"creditcard":      IsCreditCard,
	"isbn10":          IsISBN10,
	"isbn13":          IsISBN13,
	"json":            IsJSON,
	"multibyte":       IsMultibyte,
	"ascii":           IsASCII,
	"fullwidth":       IsFullWidth,
	"halfwidth":       IsHalfWidth,
	"variablewidth":   IsVariableWidth,
	"base64":          IsBase64,
	"datauri":         IsDataURI,
	"ipv4":            IsIPv4,
	"ipv6":            IsIPv6,
	"mac":             IsMAC,
	"latitude":        IsLatitude,
	"longitude":       IsLongitude,
}
<|endoftext|>


<commit_before>package class

import (
	"io"
)

// ClassFile represents a single class file as specified in:
// http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
type ClassFile struct {
	// Magic number found in all valid Java class files.
	// This will always equal 0xCAFEBABE
	Magic uint32

	// Major.Minor denotes the class file version, that
	// has to be supported by the executing JVM.
	MinorVersion uint16
	MajorVersion uint16

	// The constant pool is a table of structures
	// representing various string constants, class,
	// interface & field names and other constants that
	// are referred to in the class file structure.
	ConstPoolSize uint16
	ConstantPool

	// AccessFlags is a mask of flags used to denote
	// access permissions and properties of this class
	// or interface.
	AccessFlags

	// Index into the constant pool, where you should
	// find a CONSTANT_Class_info struct that describes
	// this class.
	ThisClass ConstPoolIndex

	// Index into the constant pool or zero, where you
	// should find a CONSTANT_Class_info struct that
	// describes this class' super class.
	// If SuperClass is zero, then this class must
	// represent the Object class.
	// For an interface, the corresponding value in the
	// constant pool, must represent the Object class.
	SuperClass ConstPoolIndex

	// Interfaces contains indexes into the constant pool,
	// where every referenced entry describes a
	// CONSTANT_Class_info struct representing a direct
	// super-interface of this class or interface.
	Interfaces []ConstPoolIndex

	// Fields contains indexes into the constant pool,
	// referencing field_info structs, giving a complete
	// description of a field in this class or interface.
	// The Fields table only contains fields declared in
	// this class or interface, not any inherited ones.
	Fields []*Field

	// Methods contains method_info structs describing
	// a method of this class or interface.
	// If neiter METHOD_ACC_NATIVE or METHOD_ACC_ABSTRACT
	// flags are set, the corresponding code for the method
	// will also be supplied.
	Methods []*Method

	// Attributes describes properties of this class or
	// interface through attribute_info structs.
	Attributes
}

// All Attributes and Constants, plus the actual class file
// have to fullfill this interface. As you can guess, it's
// used when writing the class file back to its original
// (binary) format.
type Dumper interface {
	Dump(io.Writer) error
}

// Attributes add extra/meta info to ClassFile, Field,
// Method and Code structs. Any JVM implementation or
// Java compiler, may create its own/new attribute(s).
// Though these should not effect the sematics of the program.
// http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7
type Attribute interface {
	Dumper

	Read(io.Reader, ConstantPool) error

	// Think of an Attribute value as a discriminated union.
	GetTag() AttributeType

	// In order to actually access the fields of an attribute
	// you would need a type assertion in your code. But since
	// the Java spec is quite precise on when you can expect
	// what type of attribute (in a valid class file), we can
	// provide "safe" implementations of methods for casting
	// the values, that do not require type assertions.
	// You shouldn't call any of the following functions if you
	// aren't sure about what type an Attribute actually has,
	// since if you are wrong, the function will panic.
	UnknownAttr() *UnknownAttr
	ConstantValue() *ConstantValue
	Code() *Code
	// StackMapTable() *StackMapTable
	Exceptions() *Exceptions
	InnerClasses() *InnerClasses
	EnclosingMethod() *EnclosingMethod
	Synthetic() *Synthetic
	Signature() *Signature
	SourceFile() *SourceFile
	SourceDebugExtension() *SourceDebugExtension
	LineNumberTable() *LineNumberTable
	LocalVariableTable() *LocalVariableTable
	LocalVariableTypeTable() *LocalVariableTypeTable
	Deprecated() *Deprecated
	// RuntimeVisibleAnnotations() *RuntimeVisibleAnnotations
	// RuntimeInvisibleAnnotations() *RuntimeInvisibleAnnotations
	// RuntimeVisibleParameterAnnotations() *RuntimeVisibleParameterAnnotations
	// RuntimeInvisibleParameterAnnotations() *RuntimeInvisibleParameterAnnotations
	// AnnotationDefault() *AnnotationDefault
	BootstrapMethods() *BootstrapMethods
}

// Costants reside in a class files constant pool and
// are used in various places in a class file. They can
// describe variable or method type signatures names of
// variables or other classes. The pool also contains all
// integer and string constants that can be found in the
// code (besides when the instruction lconst_1 or the like
// is used).
type Constant interface {
	Dumper

	Read(io.Reader) error

	GetTag() ConstantType

	// In order to actually access the fields of a constant
	// you would need a type assertion in your code. But since
	// the Java spec is quite precise on when you can expect
	// what type of constant (in a valid class file), we can
	// provide "safe" implementations of methods for casting
	// the values, that do not require type assertions.
	// You shouldn't call any of the following functions if you
	// aren't sure about what type a Constant actually has,
	// since if you are wrong, the function will panic.
	Class() *ClassRef
	Field() *FieldRef
	Method() *MethodRef
	InterfaceMethod() *InterfaceMethodRef
	StringRef() *StringRef
	Integer() *IntegerRef
	Float() *FloatRef
	Long() *LongRef
	Double() *DoubleRef
	NameAndType() *NameAndTypeRef
	UTF8() *UTF8Ref
	MethodHandle() *MethodHandleRef
	MethodType() *MethodTypeRef
	InvokeDynamic() *InvokeDynamicRef
}

type Attributes []Attribute
type ConstantPool []Constant

type ConstPoolIndex uint16
type AccessFlags uint16
<commit_msg>Added extra explanation of why there is still a ConstPoolSize in the ClassFile structure.<commit_after>package class

import (
	"io"
)

// ClassFile represents a single class file as specified in:
// http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
type ClassFile struct {
	// Magic number found in all valid Java class files.
	// This will always equal 0xCAFEBABE
	Magic uint32

	// Major.Minor denotes the class file version, that
	// has to be supported by the executing JVM.
	MinorVersion uint16
	MajorVersion uint16

	// The constant pool is a table of structures
	// representing various string constants, class,
	// interface & field names and other constants that
	// are referred to in the class file structure.
	// The reason we keep the ConstPoolSize instead of
	// just discarding it like with Fields and Methods,
	// is one of the most annoying bugs I've come across:
	// In the Java class file format, 64-bit constants
	// use up two spaces everywhere. So finding the size
	// of the constant pool is not just len(ConstantPool).
	ConstPoolSize uint16
	ConstantPool

	// AccessFlags is a mask of flags used to denote
	// access permissions and properties of this class
	// or interface.
	AccessFlags

	// Index into the constant pool, where you should
	// find a CONSTANT_Class_info struct that describes
	// this class.
	ThisClass ConstPoolIndex

	// Index into the constant pool or zero, where you
	// should find a CONSTANT_Class_info struct that
	// describes this class' super class.
	// If SuperClass is zero, then this class must
	// represent the Object class.
	// For an interface, the corresponding value in the
	// constant pool, must represent the Object class.
	SuperClass ConstPoolIndex

	// Interfaces contains indexes into the constant pool,
	// where every referenced entry describes a
	// CONSTANT_Class_info struct representing a direct
	// super-interface of this class or interface.
	Interfaces []ConstPoolIndex

	// Fields contains indexes into the constant pool,
	// referencing field_info structs, giving a complete
	// description of a field in this class or interface.
	// The Fields table only contains fields declared in
	// this class or interface, not any inherited ones.
	Fields []*Field

	// Methods contains method_info structs describing
	// a method of this class or interface.
	// If neiter METHOD_ACC_NATIVE or METHOD_ACC_ABSTRACT
	// flags are set, the corresponding code for the method
	// will also be supplied.
	Methods []*Method

	// Attributes describes properties of this class or
	// interface through attribute_info structs.
	Attributes
}

// All Attributes and Constants, plus the actual class file
// have to fullfill this interface. As you can guess, it's
// used when writing the class file back to its original
// (binary) format.
type Dumper interface {
	Dump(io.Writer) error
}

// Attributes add extra/meta info to ClassFile, Field,
// Method and Code structs. Any JVM implementation or
// Java compiler, may create its own/new attribute(s).
// Though these should not effect the sematics of the program.
// http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7
type Attribute interface {
	Dumper

	Read(io.Reader, ConstantPool) error

	// Think of an Attribute value as a discriminated union.
	GetTag() AttributeType

	// In order to actually access the fields of an attribute
	// you would need a type assertion in your code. But since
	// the Java spec is quite precise on when you can expect
	// what type of attribute (in a valid class file), we can
	// provide "safe" implementations of methods for casting
	// the values, that do not require type assertions.
	// You shouldn't call any of the following functions if you
	// aren't sure about what type an Attribute actually has,
	// since if you are wrong, the function will panic.
	UnknownAttr() *UnknownAttr
	ConstantValue() *ConstantValue
	Code() *Code
	// StackMapTable() *StackMapTable
	Exceptions() *Exceptions
	InnerClasses() *InnerClasses
	EnclosingMethod() *EnclosingMethod
	Synthetic() *Synthetic
	Signature() *Signature
	SourceFile() *SourceFile
	SourceDebugExtension() *SourceDebugExtension
	LineNumberTable() *LineNumberTable
	LocalVariableTable() *LocalVariableTable
	LocalVariableTypeTable() *LocalVariableTypeTable
	Deprecated() *Deprecated
	// RuntimeVisibleAnnotations() *RuntimeVisibleAnnotations
	// RuntimeInvisibleAnnotations() *RuntimeInvisibleAnnotations
	// RuntimeVisibleParameterAnnotations() *RuntimeVisibleParameterAnnotations
	// RuntimeInvisibleParameterAnnotations() *RuntimeInvisibleParameterAnnotations
	// AnnotationDefault() *AnnotationDefault
	BootstrapMethods() *BootstrapMethods
}

// Costants reside in a class files constant pool and
// are used in various places in a class file. They can
// describe variable or method type signatures names of
// variables or other classes. The pool also contains all
// integer and string constants that can be found in the
// code (besides when the instruction lconst_1 or the like
// is used).
type Constant interface {
	Dumper

	Read(io.Reader) error

	GetTag() ConstantType

	// In order to actually access the fields of a constant
	// you would need a type assertion in your code. But since
	// the Java spec is quite precise on when you can expect
	// what type of constant (in a valid class file), we can
	// provide "safe" implementations of methods for casting
	// the values, that do not require type assertions.
	// You shouldn't call any of the following functions if you
	// aren't sure about what type a Constant actually has,
	// since if you are wrong, the function will panic.
	Class() *ClassRef
	Field() *FieldRef
	Method() *MethodRef
	InterfaceMethod() *InterfaceMethodRef
	StringRef() *StringRef
	Integer() *IntegerRef
	Float() *FloatRef
	Long() *LongRef
	Double() *DoubleRef
	NameAndType() *NameAndTypeRef
	UTF8() *UTF8Ref
	MethodHandle() *MethodHandleRef
	MethodType() *MethodTypeRef
	InvokeDynamic() *InvokeDynamicRef
}

type Attributes []Attribute
type ConstantPool []Constant

type ConstPoolIndex uint16
type AccessFlags uint16
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package maps contains TODO(brettmorgan)
//
// More information about Google Distance Matrix API is available on
// https://developers.google.com/maps/documentation/distancematrix/
package maps // import "google.golang.org/maps"
import "time"

const (
	// ModeDriving is for specifying driving as travel mode
	ModeDriving = "driving"
	// ModeWalking is for specifying walking as travel mode
	ModeWalking = "walking"
	// ModeBicycling is for specifying bicycling as travel mode
	ModeBicycling = "bicycling"
	// ModeTransit is for specifying transit as travel mode
	ModeTransit = "transit"

	// AvoidTolls is for specifying routes that avoid tolls
	AvoidTolls = "tolls"
	// AvoidHighways is for specifying routes that avoid highways
	AvoidHighways = "highways"
	// AvoidFerries is for specifying routes that avoid ferries
	AvoidFerries = "ferries"

	// UnitsMetric specifies usage of the metric units system
	UnitsMetric = "metric"
	// UnitsImperial specifies usage of the Imperial (English) units system
	UnitsImperial = "imperial"

	// TransitModeBus is for specifying a transit mode of bus
	TransitModeBus = "bus"
	// TransitModeSubway is for specifying a transit mode of subway
	TransitModeSubway = "subway"
	// TransitModeTrain is for specifying a transit mode of train
	TransitModeTrain = "train"
	// TransitModeTram is for specifying a transit mode of tram
	TransitModeTram = "tram"
	// TransitModeRail is for specifying a transit mode of rail
	TransitModeRail = "rail"

	// TransitRoutingPreferenceLessWalking indicates that the calculated route should prefer limited amounts of walking
	TransitRoutingPreferenceLessWalking = "less_walking"
	// TransitRoutingPreferenceFewerTransfers indicates that the calculated route should prefer a limited number of transfers
	TransitRoutingPreferenceFewerTransfers = "fewer_transfers"
)

// DistanceMatrixRequest is the functional options struct for DistanceMatrixGet
type DistanceMatrixRequest struct {
	Origins                  []string
	Destinations             []string
	Mode                     string
	Language                 string
	Avoid                    string
	Units                    string
	DepartureTime            string
	ArrivalTime              string
	TransitMode              string
	TransitRoutingPreference string
}

// DistanceMatrixResponse represents a Distance Matrix API response.
type DistanceMatrixResponse struct {

	// OriginAddresses contains an array of addresses as returned by the API from your original request.
	OriginAddresses []string `json:"origin_addresses"`
	// DestinationAddresses contains an array of addresses as returned by the API from your original request.
	DestinationAddresses []string `json:"destination_addresses"`
	//Rows contains an array of elements.
	Rows []DistanceMatrixElementsRow `json:"rows"`

	// Status contains the status of the request, and may contain
	// debugging information to help you track down why the Directions
	// service failed.
	// See https://developers.google.com/maps/documentation/distancematrix/#StatusCodes
	Status string `json:"status"`

	// ErrorMessage is the explanatory field added when Status is an error.
	ErrorMessage string `json:"error_message"`
}

// DistanceMatrixElementsRow is a row of distance elements.
type DistanceMatrixElementsRow struct {
	Elements []*DistanceMatrixElement `json:"elements"`
}

// DistanceMatrixElement is the travel distance and time for a pair of origin and destination.
type DistanceMatrixElement struct {
	Status   string        `json:"status"`
	Duration time.Duration `json:"duration"`
	Distance Distance      `json:"distance"`
}

// Distance is the API representation for a distance between two points.
type Distance struct {
	// Text is the distance in a human displayable form. The style of display can be changed by setting `units`.
	Text string `json:"text"`
	// Value is the distance in meters.
	Value int `json:"value"`
}
<commit_msg>Tidyup docs<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package maps contains TODO(brettmorgan)
//
// More information about Google Distance Matrix API is available on
// https://developers.google.com/maps/documentation/distancematrix/
package maps // import "google.golang.org/maps"
import "time"

const (
	// ModeDriving is for specifying driving as travel mode
	ModeDriving = "driving"
	// ModeWalking is for specifying walking as travel mode
	ModeWalking = "walking"
	// ModeBicycling is for specifying bicycling as travel mode
	ModeBicycling = "bicycling"
	// ModeTransit is for specifying transit as travel mode
	ModeTransit = "transit"

	// AvoidTolls is for specifying routes that avoid tolls
	AvoidTolls = "tolls"
	// AvoidHighways is for specifying routes that avoid highways
	AvoidHighways = "highways"
	// AvoidFerries is for specifying routes that avoid ferries
	AvoidFerries = "ferries"

	// UnitsMetric specifies usage of the metric units system
	UnitsMetric = "metric"
	// UnitsImperial specifies usage of the Imperial (English) units system
	UnitsImperial = "imperial"

	// TransitModeBus is for specifying a transit mode of bus
	TransitModeBus = "bus"
	// TransitModeSubway is for specifying a transit mode of subway
	TransitModeSubway = "subway"
	// TransitModeTrain is for specifying a transit mode of train
	TransitModeTrain = "train"
	// TransitModeTram is for specifying a transit mode of tram
	TransitModeTram = "tram"
	// TransitModeRail is for specifying a transit mode of rail
	TransitModeRail = "rail"

	// TransitRoutingPreferenceLessWalking indicates that the calculated route should prefer limited amounts of walking
	TransitRoutingPreferenceLessWalking = "less_walking"
	// TransitRoutingPreferenceFewerTransfers indicates that the calculated route should prefer a limited number of transfers
	TransitRoutingPreferenceFewerTransfers = "fewer_transfers"
)

// DistanceMatrixRequest is the functional options struct for DistanceMatrixGet
type DistanceMatrixRequest struct {
	Origins                  []string
	Destinations             []string
	Mode                     string
	Language                 string
	Avoid                    string
	Units                    string
	DepartureTime            string
	ArrivalTime              string
	TransitMode              string
	TransitRoutingPreference string
}

// DistanceMatrixResponse represents a Distance Matrix API response.
type DistanceMatrixResponse struct {

	// OriginAddresses contains an array of addresses as returned by the API from your original request.
	OriginAddresses []string `json:"origin_addresses"`
	// DestinationAddresses contains an array of addresses as returned by the API from your original request.
	DestinationAddresses []string `json:"destination_addresses"`
	// Rows contains an array of elements.
	Rows []DistanceMatrixElementsRow `json:"rows"`

	// Status contains the status of the request, and may contain
	// debugging information to help you track down why the Directions
	// service failed.
	// See https://developers.google.com/maps/documentation/distancematrix/#StatusCodes
	Status string `json:"status"`

	// ErrorMessage is the explanatory field added when Status is an error.
	ErrorMessage string `json:"error_message"`
}

// DistanceMatrixElementsRow is a row of distance elements.
type DistanceMatrixElementsRow struct {
	Elements []*DistanceMatrixElement `json:"elements"`
}

// DistanceMatrixElement is the travel distance and time for a pair of origin and destination.
type DistanceMatrixElement struct {
	Status   string        `json:"status"`
	Duration time.Duration `json:"duration"`
	Distance Distance      `json:"distance"`
}

// Distance is the API representation for a distance between two points.
type Distance struct {
	// Text is the distance in a human displayable form. The style of display can be changed by setting `units`.
	Text string `json:"text"`
	// Value is the distance in meters.
	Value int `json:"value"`
}
<|endoftext|>


<commit_before>// +build linux,!gccgo
package mount
/*
	As per the setns documentation, it is impossible to enter a
	mount namespace from a multithreaded process.
	One MUST insure that opening the namespace happens when the process
	has only one thread. This is impossible from golang, as such we call
	this C function as a constructor to ensure that it is executed
	before the go scheduler launches other threads.
*/
// extern int enter_mount_namespace(void);
/*
#include <stdlib.h>
__attribute__((constructor)) void init(void) {
	if (enter_mount_namespace() < 0) {
		exit(EXIT_FAILURE);
	}
}
*/
import "C"

import (
	"fmt"
	"os"
	"path"
	"strings"

	"github.com/subgraph/oz"
	"github.com/subgraph/oz/fs"

	"github.com/op/go-logging"
)

const (
	MOUNT = 1 << iota
	UMOUNT
)

func Main(mode int) {
	log := createLogger()
	config, err := loadConfig()
	if err != nil {
		log.Error("Could not load configuration: %s (%+v)", oz.DefaultConfigPath, err)
		os.Exit(1)
	}

	fsys := fs.NewFilesystem(config, log)
	homedir :=  os.Getenv("_OZ_HOMEDIR")
	if homedir == "" {
		log.Error("Homedir must be set!")
		os.Exit(1)
	}

	start := 1
	readonly := false
	if os.Args[1] == "--readonly" {
		start = 2
		readonly = true
	}
	for _, fpath := range os.Args[start:] {
		cpath, err := cleanPath(fpath, homedir)
		if (err != nil || cpath == "") {
			log.Error("%v", err)
			os.Exit(1)
		}
		switch mode {
		case MOUNT:
			mount(cpath, readonly, fsys, log)
		case UMOUNT:
			unmount(cpath, fsys, log)
		default:
			log.Error("Unknown mode!")
			os.Exit(1)
		}
	}

	os.Exit(0)
}

func cleanPath(spath, homedir string) (string, error) {
	spath = path.Clean(spath)
	if !path.IsAbs(spath) {
		spath = path.Join(homedir, spath)
	}
	if !strings.HasPrefix(spath, homedir) {
		return "", fmt.Errorf("only files inside of the user home are permitted")
	}
	return spath, nil
}

func mount(fpath string, readonly bool, fsys *fs.Filesystem, log *logging.Logger) {
	//log.Notice("Adding file `%s`.", fpath)
	// TODO: Check if target is empty directory (and not a mountpoint) and allow the bind in that case
	if _, err := os.Stat(fpath); err != nil {
		log.Error("%v", err)
		os.Exit(1)
	}
	flags := fs.BindCanCreate
	if readonly {
		flags |= fs.BindReadOnly
	}
	if err := fsys.BindPath(fpath, flags, nil); err != nil {
		log.Error("%v", err)
		os.Exit(1)
	}
}

func unmount(fpath string, fsys *fs.Filesystem, log *logging.Logger) {
	sbpath := path.Join(fsys.Root(), fpath)
	if _, err := os.Stat(sbpath); err == nil {
		//log.Notice("Removing file `%s`.", fpath)
		if err := fsys.UnbindPath(fpath); err != nil {
			log.Error("%v", err)
			os.Exit(1)
		}
	} else {
		log.Warning("%v", err)
	}
}

func createLogger() *logging.Logger {
	l := logging.MustGetLogger("oz-init")
	be := logging.NewLogBackend(os.Stdout, "", 0)
	f := logging.MustStringFormatter("%{level:.1s} %{message}")
	fbe := logging.NewBackendFormatter(be, f)
	logging.SetBackend(fbe)
	return l
}

func loadConfig() (*oz.Config, error) {
	config, err := oz.LoadConfig(oz.DefaultConfigPath)
	if err != nil {
		if os.IsNotExist(err) {
			config = oz.NewDefaultConfig()
		} else {
			return nil, err
		}
	}

	return config, nil
}
<commit_msg>Comment broke build, temporarily removing this<commit_after>// +build linux,!gccgo
package mount
// extern int enter_mount_namespace(void);
/*
#include <stdlib.h>
__attribute__((constructor)) void init(void) {
	if (enter_mount_namespace() < 0) {
		exit(EXIT_FAILURE);
	}
}
*/
import "C"

import (
	"fmt"
	"os"
	"path"
	"strings"

	"github.com/subgraph/oz"
	"github.com/subgraph/oz/fs"

	"github.com/op/go-logging"
)

const (
	MOUNT = 1 << iota
	UMOUNT
)

func Main(mode int) {
	log := createLogger()
	config, err := loadConfig()
	if err != nil {
		log.Error("Could not load configuration: %s (%+v)", oz.DefaultConfigPath, err)
		os.Exit(1)
	}

	fsys := fs.NewFilesystem(config, log)
	homedir :=  os.Getenv("_OZ_HOMEDIR")
	if homedir == "" {
		log.Error("Homedir must be set!")
		os.Exit(1)
	}

	start := 1
	readonly := false
	if os.Args[1] == "--readonly" {
		start = 2
		readonly = true
	}
	for _, fpath := range os.Args[start:] {
		cpath, err := cleanPath(fpath, homedir)
		if (err != nil || cpath == "") {
			log.Error("%v", err)
			os.Exit(1)
		}
		switch mode {
		case MOUNT:
			mount(cpath, readonly, fsys, log)
		case UMOUNT:
			unmount(cpath, fsys, log)
		default:
			log.Error("Unknown mode!")
			os.Exit(1)
		}
	}

	os.Exit(0)
}

func cleanPath(spath, homedir string) (string, error) {
	spath = path.Clean(spath)
	if !path.IsAbs(spath) {
		spath = path.Join(homedir, spath)
	}
	if !strings.HasPrefix(spath, homedir) {
		return "", fmt.Errorf("only files inside of the user home are permitted")
	}
	return spath, nil
}

func mount(fpath string, readonly bool, fsys *fs.Filesystem, log *logging.Logger) {
	//log.Notice("Adding file `%s`.", fpath)
	// TODO: Check if target is empty directory (and not a mountpoint) and allow the bind in that case
	if _, err := os.Stat(fpath); err != nil {
		log.Error("%v", err)
		os.Exit(1)
	}
	flags := fs.BindCanCreate
	if readonly {
		flags |= fs.BindReadOnly
	}
	if err := fsys.BindPath(fpath, flags, nil); err != nil {
		log.Error("%v", err)
		os.Exit(1)
	}
}

func unmount(fpath string, fsys *fs.Filesystem, log *logging.Logger) {
	sbpath := path.Join(fsys.Root(), fpath)
	if _, err := os.Stat(sbpath); err == nil {
		//log.Notice("Removing file `%s`.", fpath)
		if err := fsys.UnbindPath(fpath); err != nil {
			log.Error("%v", err)
			os.Exit(1)
		}
	} else {
		log.Warning("%v", err)
	}
}

func createLogger() *logging.Logger {
	l := logging.MustGetLogger("oz-init")
	be := logging.NewLogBackend(os.Stdout, "", 0)
	f := logging.MustStringFormatter("%{level:.1s} %{message}")
	fbe := logging.NewBackendFormatter(be, f)
	logging.SetBackend(fbe)
	return l
}

func loadConfig() (*oz.Config, error) {
	config, err := oz.LoadConfig(oz.DefaultConfigPath)
	if err != nil {
		if os.IsNotExist(err) {
			config = oz.NewDefaultConfig()
		} else {
			return nil, err
		}
	}

	return config, nil
}
<|endoftext|>